diff --git a/.github/workflows/dev_cippacnqv.yml b/.github/workflows/dev_cippacnqv.yml new file mode 100644 index 000000000000..67a58b70c7ff --- /dev/null +++ b/.github/workflows/dev_cippacnqv.yml @@ -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 }} + \ No newline at end of file diff --git a/Cache_SAMSetup/SAMManifest.json b/Cache_SAMSetup/SAMManifest.json index b6b291da57b4..f1a5bb8d77a3 100644 --- a/Cache_SAMSetup/SAMManifest.json +++ b/Cache_SAMSetup/SAMManifest.json @@ -159,7 +159,9 @@ { "id": "cb8f45a0-5c2e-4ea1-b803-84b870a7d7ec", "type": "Scope" }, { "id": "4c06a06a-098a-4063-868e-5dfee3827264", "type": "Scope" }, { "id": "1bfefb4e-e0b5-418b-a88f-73c46d2cc8e9", "type": "Role" }, - { "id": "e67e6727-c080-415e-b521-e3f35d5248e9", "type": "Scope" } + { "id": "e67e6727-c080-415e-b521-e3f35d5248e9", "type": "Scope" }, + { "id": "b6890674-9dd5-4e42-bb15-5af07f541ae1", "type": "Role" } + ] }, { diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertQuotaUsed.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertQuotaUsed.ps1 index 32b63925c02a..5d6a4faf5bd8 100644 --- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertQuotaUsed.ps1 +++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertQuotaUsed.ps1 @@ -17,9 +17,17 @@ function Get-CIPPAlertQuotaUsed { return } $AlertData | ForEach-Object { - if ($_.StorageUsedInBytes -eq 0) { return } + 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" } diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertSharepointQuota.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertSharepointQuota.ps1 index 4cb04042f495..e8cefb6d0bd2 100644 --- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertSharepointQuota.ps1 +++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertSharepointQuota.ps1 @@ -12,7 +12,7 @@ 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' -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 @@ -20,7 +20,11 @@ function Get-CIPPAlertSharepointQuota { 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)%" diff --git a/Modules/CIPPCore/Public/CippQueue/Invoke-ListCippQueue.ps1 b/Modules/CIPPCore/Public/CippQueue/Invoke-ListCippQueue.ps1 index ef4357efefd5..209432df45dd 100644 --- a/Modules/CIPPCore/Public/CippQueue/Invoke-ListCippQueue.ps1 +++ b/Modules/CIPPCore/Public/CippQueue/Invoke-ListCippQueue.ps1 @@ -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 diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-DomainAnalyserDomain.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-DomainAnalyserDomain.ps1 index 5366603a4492..9952ff679677 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-DomainAnalyserDomain.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-DomainAnalyserDomain.ps1 @@ -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 @@ -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 } \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-DomainAnalyserTenant.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-DomainAnalyserTenant.ps1 index 605c56bebb53..440f7e37d4cf 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-DomainAnalyserTenant.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-DomainAnalyserTenant.ps1 @@ -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]@{ @@ -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) { diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 index 20746f57fa52..e94a5d904bf1 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 @@ -62,12 +62,12 @@ function Push-ExecScheduledCommand { $TableDesign = '' $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 '', "This alert is for tenant $tenant.

$TableDesign
" | 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogBundleProcessing.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogBundleProcessing.ps1 new file mode 100644 index 000000000000..13f2315e94a8 --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogBundleProcessing.ps1 @@ -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) + } +} \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenant.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenant.ps1 new file mode 100644 index 000000000000..0f4c03e1c833 --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenant.ps1 @@ -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'" + } + +} \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-PublicWebhookProcess.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-PublicWebhookProcess.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-PublicWebhookProcess.ps1 rename to Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-PublicWebhookProcess.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-Schedulerwebhookcreation.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-Schedulerwebhookcreation.ps1 similarity index 82% rename from Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-Schedulerwebhookcreation.ps1 rename to Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-Schedulerwebhookcreation.ps1 index 8c56ccb98971..47aa38b1a072 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-Schedulerwebhookcreation.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-Schedulerwebhookcreation.ps1 @@ -23,7 +23,7 @@ function Push-Schedulerwebhookcreation { 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 '2' and Resource eq '$($Row.webhookType)'" + $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') { @@ -32,17 +32,14 @@ function Push-Schedulerwebhookcreation { } else { Write-Host "No existing webhook for $Tenant - $($Row.webhookType) - Time to create." try { - $NewSub = New-CIPPGraphSubscription -TenantFilter $Tenant -EventType $Row.webhookType -BaseURL $Row.CIPPURL -auditLogAPI $true + $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)" - Write-LogMessage -message "Failed to create webhook for $Tenant - $($Row.webhookType)" -Sev 'Error' -LogData $_.Exception } } catch { 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 - } } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCustomRole.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCustomRole.ps1 index a1e92d2c3f89..c5725a2cafb8 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCustomRole.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCustomRole.ps1 @@ -14,7 +14,7 @@ function Invoke-ExecCustomRole { Write-LogMessage -user $Request.Headers.'x-ms-client-principal' -API 'ExecCustomRole' -message "Saved custom role $($Request.Body.RoleName)" -Sev 'Info' $Role = @{ 'PartitionKey' = 'CustomRoles' - 'RowKey' = "$($Request.Body.RoleName)" + 'RowKey' = "$($Request.Body.RoleName.ToLower())" 'Permissions' = "$($Request.Body.Permissions | ConvertTo-Json -Compress)" 'AllowedTenants' = "$($Request.Body.AllowedTenants | ConvertTo-Json -Compress)" 'BlockedTenants' = "$($Request.Body.BlockedTenants | ConvertTo-Json -Compress)" diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSharedMailbox.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSharedMailbox.ps1 index 20af9ebdd475..188dfa89adfd 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSharedMailbox.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSharedMailbox.ps1 @@ -16,46 +16,58 @@ Function Invoke-AddSharedMailbox { Write-LogMessage -user $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' $Results = [System.Collections.ArrayList]@() - $groupobj = $Request.body - $Aliases = $groupobj.addedAliases -Split '\n' + $MailboxObject = $Request.body + $Aliases = $MailboxObject.addedAliases -Split '\n' # Write to the Azure Functions log stream. Write-Host 'PowerShell HTTP trigger function processed a request.' try { - $Email = "$($groupobj.username)@$($groupobj.domain)" - $BodyToship = [pscustomobject] @{ - 'displayName' = $groupobj.Displayname - 'name' = $groupobj.username + $Email = "$($MailboxObject.username)@$($MailboxObject.domain)" + $BodyToShip = [pscustomobject] @{ + 'displayName' = $MailboxObject.Displayname + 'name' = $MailboxObject.username 'primarySMTPAddress' = $Email Shared = $true } - $AddSharedRequest = New-ExoRequest -tenantid $groupobj.tenantid -cmdlet 'New-Mailbox' -cmdparams $BodyToship + $AddSharedRequest = New-ExoRequest -tenantid $MailboxObject.tenantid -cmdlet 'New-Mailbox' -cmdparams $BodyToShip $Body = $Results.add("Successfully created shared mailbox: $Email.") - Write-LogMessage -user $User -API $APINAME -tenant $($groupobj.tenantid) -message "Created shared mailbox $($groupobj.displayname) with email $Email" -Sev 'Info' + Write-LogMessage -user $User -API $APINAME -tenant $($MailboxObject.tenantid) -message "Created shared mailbox $($MailboxObject.displayname) with email $Email" -Sev 'Info' } catch { - Write-LogMessage -user $User -API $APINAME -tenant $($groupobj.tenantid) -message "Failed to create shared mailbox. Error: $($_.Exception.Message)" -Sev 'Error' - $Body = $Results.add("Failed to create Shared Mailbox. $($_.Exception.Message)") - + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -user $User -API $APINAME -tenant $($MailboxObject.tenantid) -message "Failed to create shared mailbox. Error: $ErrorMessage" -Sev 'Error' + $Body = $Results.add("Failed to create Shared Mailbox. $ErrorMessage") } + # Block sign-in for the mailbox try { - if ($Aliases) { + $null = Set-CIPPSignInState -userid $AddSharedRequest.ExternalDirectoryObjectId -TenantFilter $($MailboxObject.tenantid) -APIName $APINAME -ExecutingUser $User -AccountEnabled $false + Write-LogMessage -user $User -API $APINAME -tenant $($MailboxObject.tenantid) -message "Blocked sign-in for shared mailbox $Email" -Sev 'Info' + $Body = $Results.add("Blocked sign-in for shared mailbox $Email") + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -user $User -API $APINAME -tenant $($MailboxObject.tenantid) -message "Failed to block sign-in for shared mailbox $Email. Error: $ErrorMessage" -Sev 'Error' + $Body = $Results.add("Failed to block sign-in for shared mailbox $Email. Error: $ErrorMessage") + } + # Add aliases to the mailbox if any are provided + if ($Aliases) { + try { Start-Sleep 3 # Sleep since there is apparently a race condition with the mailbox creation if we don't delay for a lil bit $AliasBodyToShip = [pscustomobject] @{ 'Identity' = $AddSharedRequest.Guid 'EmailAddresses' = @{'@odata.type' = '#Exchange.GenericHashTable'; Add = $Aliases } } - $AliasBodyToShip - New-ExoRequest -tenantid $groupobj.tenantid -cmdlet 'Set-Mailbox' -cmdparams $AliasBodyToShip -UseSystemMailbox $true - Write-LogMessage -user $User -API $APINAME -tenant $($groupobj.tenantid) -message "Added aliases to $Email : $($Aliases -join ',')" -Sev 'Info' + $null = New-ExoRequest -tenantid $MailboxObject.tenantid -cmdlet 'Set-Mailbox' -cmdparams $AliasBodyToShip -UseSystemMailbox $true + Write-LogMessage -user $User -API $APINAME -tenant $($MailboxObject.tenantid) -message "Added aliases to $Email : $($Aliases -join ',')" -Sev 'Info' $Body = $results.add("Added Aliases to $Email : $($Aliases -join ',')") + + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -user $User -API $APINAME -tenant $($MailboxObject.tenantid) -message "Failed to add aliases to $Email : $ErrorMessage" -Sev 'Error' + $Body = $results.add("ERROR: Failed to add aliases to $Email : $ErrorMessage") } - } catch { - Write-LogMessage -user $User -API $APINAME -tenant $($groupobj.tenantid) -message "Failed to add aliases to $Email : $($_.Exception.Message)" -Sev 'Error' - $Body = $results.add("ERROR: Failed to add aliases to $Email : $($_.Exception.Message)") } $Body = [pscustomobject] @{ 'Results' = @($results) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSpamFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSpamFilter.ps1 index deb78b344897..a27660da63c5 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSpamFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSpamFilter.ps1 @@ -15,6 +15,7 @@ Function Invoke-AddSpamFilter { Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' $RequestParams = $Request.Body.PowerShellCommand | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty GUID, comments + $RequestPriority = $Request.Body.Priority $Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value $Result = foreach ($Tenantfilter in $tenants) { @@ -26,6 +27,7 @@ Function Invoke-AddSpamFilter { 'hostedcontentfilterpolicy' = "$($RequestParams.name)" 'recipientdomainis' = @($domains) 'Enabled' = $true + 'Priority' = $RequestPriority } $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet 'New-HostedContentFilterRule' -cmdParams $ruleparams "Successfully created spamfilter for $tenantfilter." diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailboxMobileDevices.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailboxMobileDevices.ps1 index 7b58b76afc7c..b633755f759b 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailboxMobileDevices.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailboxMobileDevices.ps1 @@ -20,7 +20,7 @@ Function Invoke-ExecMailboxMobileDevices { # Interact with query parameters or the body of the request. Try { - $MobileResults = Set-CIPPMobileDevice -UserId $request.query.Userid -DeviceId $request.query.deviceid -Quarantine $request.query.Quarantine -tenantFilter $request.query.tenantfilter -APIName $APINAME -Delete $Request.query.Delete -ExecutingUser $request.headers.'x-ms-client-principal' + $MobileResults = Set-CIPPMobileDevice -UserId $request.query.Userid -Guid $request.query.guid -DeviceId $request.query.deviceid -Quarantine $request.query.Quarantine -tenantFilter $request.query.tenantfilter -APIName $APINAME -Delete $Request.query.Delete -ExecutingUser $request.headers.'x-ms-client-principal' $Results = [pscustomobject]@{'Results' = $MobileResults } } catch { $Results = [pscustomobject]@{'Results' = "Failed $($request.query.Userid): $($_.Exception.Message)" } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-EditGroup.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-EditGroup.ps1 index 122c4f118739..9deb382c2d85 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-EditGroup.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-EditGroup.ps1 @@ -130,19 +130,11 @@ Function Invoke-EditGroup { if ($userobj.allowExternal -eq 'true') { try { - if ($userobj.groupType -eq 'Distribution list') { - $Params = @{ Identity = $userobj.groupid; RequireSenderAuthenticationEnabled = $false } - New-ExoRequest -tenantid $Userobj.tenantid -cmdlet 'Set-DistributionGroup' -cmdParams $params - } else { - $Params = @{ Identity = $userobj.groupid; RequireSenderAuthenticationEnabled = $false } - New-ExoRequest -tenantid $Userobj.tenantid -cmdlet 'Set-UnifiedGroup' -cmdParams $params - } - $body = $results.add("Allowed external senders to send to $($userobj.groupName).") - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Allowed external senders to send to $($userobj.groupName)" -Sev 'Info' - + Set-CIPPGroupAuthentication -ID $userobj.mail -GroupType $userobj.groupType -tenantFilter $Userobj.tenantid -APIName $APINAME -ExecutingUser $request.headers.'x-ms-client-principal' + $body = $results.add("Allowed external senders to send to $($userobj.mail).") } catch { - $body = $results.add("Failed to allow external senders to send to $($userobj.groupName).") - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Failed to allow external senders for $($userobj.groupName). Error:$($_.Exception.Message)" -Sev 'Error' + $body = $results.add("Failed to allow external senders to send to $($userobj.mail).") + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $Userobj.tenantid -message "Failed to allow external senders for $($userobj.mail). Error:$($_.Exception.Message)" -Sev 'Error' } } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDisableUser.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDisableUser.ps1 index 69ac4dd83ec8..b5b80a86d7c8 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDisableUser.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDisableUser.ps1 @@ -12,11 +12,11 @@ Function Invoke-ExecDisableUser { $APIName = $TriggerMetadata.FunctionName try { - ([System.Convert]::ToBoolean($Request.Query.Enable)) $State = Set-CIPPSignInState -userid $Request.query.ID -TenantFilter $Request.Query.TenantFilter -APIName $APINAME -ExecutingUser $request.headers.'x-ms-client-principal' -AccountEnabled ([System.Convert]::ToBoolean($Request.Query.Enable)) $Results = [pscustomobject]@{'Results' = "$State" } } catch { - $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" } + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + $Results = [pscustomobject]@{'Results' = "Failed. $ErrorMessage" } } # Associate values to output bindings by calling 'Push-OutputBinding'. diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecJITAdmin.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecJITAdmin.ps1 index 1c1c575a598f..f9dbca2ab349 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecJITAdmin.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecJITAdmin.ps1 @@ -21,7 +21,7 @@ Function Invoke-ExecJITAdmin { Endpoint = 'users' Parameters = @{ '$count' = 'true' - '$select' = "id,displayName,userPrincipalName,$($Schema.id)" + '$select' = "id,accountEnabled,displayName,userPrincipalName,$($Schema.id)" '$filter' = "$($Schema.id)/jitAdminEnabled eq true or $($Schema.id)/jitAdminEnabled eq false" } } @@ -42,6 +42,7 @@ Function Invoke-ExecJITAdmin { id = $_.id displayName = $_.displayName userPrincipalName = $_.userPrincipalName + accountEnabled = $_.accountEnabled jitAdminEnabled = $_.($Schema.id).jitAdminEnabled jitAdminExpiration = $_.($Schema.id).jitAdminExpiration memberOf = $MemberOf @@ -56,10 +57,11 @@ Function Invoke-ExecJITAdmin { } } } else { - Write-LogMessage -user $Request.Headers.'x-ms-client-principal' -API $APINAME -message "Executing JIT Admin for $($Request.Body.UserPrincipalName)" -Sev 'Info' + if ($Request.Body.UserId -match '^[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}$') { $Username = (New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/users/$($Request.Body.UserId)" -tenantid $Request.Body.TenantFilter).userPrincipalName } + Write-LogMessage -user $Request.Headers.'x-ms-client-principal' -API $APINAME -message "Executing JIT Admin for $Username" -Sev 'Info' $Start = ([System.DateTimeOffset]::FromUnixTimeSeconds($Request.Body.StartDate)).DateTime.ToLocalTime() $Expiration = ([System.DateTimeOffset]::FromUnixTimeSeconds($Request.Body.EndDate)).DateTime.ToLocalTime() @@ -81,9 +83,44 @@ Function Invoke-ExecJITAdmin { $CreateResult = Set-CIPPUserJITAdmin @JITAdmin $Username = $CreateResult.userPrincipalName $Results.Add("Created User: $($CreateResult.userPrincipalName)") - $Results.Add("Password: $($CreateResult.password)") + if (!$Request.Body.UseTAP) { + $Results.Add("Password: $($CreateResult.password)") + } + $Results.Add("JIT Expires: $($Expiration)") Start-Sleep -Seconds 1 } + + if ($Request.Body.UseTAP) { + try { + if ($Start -gt (Get-Date)) { + $TapParams = @{ + startDateTime = [System.DateTimeOffset]::FromUnixTimeSeconds($Request.Body.StartDate).DateTime + } + $TapBody = ConvertTo-Json -Depth 5 -InputObject $TapParams + } else { + $TapBody = '{}' + } + Write-Information "https://graph.microsoft.com/beta/users/$Username/authentication/temporaryAccessPassMethods" + $TapRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($Username)/authentication/temporaryAccessPassMethods" -tenantid $Request.Body.TenantFilter -type POST -body $TapBody + + $TempPass = $TapRequest.temporaryAccessPass + $PasswordExpiration = $TapRequest.LifetimeInMinutes + + $PasswordLink = New-PwPushLink -Payload $TempPass + if ($PasswordLink) { + $Password = $PasswordLink + } + $Results.Add("Temporary Access Pass: $Password") + $Results.Add("This TAP is usable starting at $($TapRequest.startDateTime) UTC for the next $PasswordExpiration minutes") + } catch { + $Results.Add('Failed to create TAP, if this is not yet enabled, use the Standards to push the settings to the tenant.') + Write-Information (Get-CippException -Exception $_ | ConvertTo-Json -Depth 5) + if ($Password) { + $Results.Add("Password: $Password") + } + } + } + $Parameters = @{ TenantFilter = $Request.Body.TenantFilter User = @{ diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecRevokeSessions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecRevokeSessions.ps1 index 5c5c56fe568f..a17b40139b05 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecRevokeSessions.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecRevokeSessions.ps1 @@ -16,7 +16,7 @@ Function Invoke-ExecRevokeSessions { # Interact with query parameters or the body of the request. $TenantFilter = $Request.Query.TenantFilter try { - $RevokeSessions = Revoke-CIPPSessions -userid $Request.Query.id -tenantFilter $TenantFilter -APIName $APINAME -ExecutingUser $request.headers.'x-ms-client-principal' + $RevokeSessions = Revoke-CIPPSessions -userid $Request.Query.id -tenantFilter $TenantFilter -username $Request.Query.Username -APIName $APINAME -ExecutingUser $request.headers.'x-ms-client-principal' $Results = [pscustomobject]@{'Results' = $RevokeSessions } } catch { $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSharePointOwner.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSharePointPerms.ps1 similarity index 89% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSharePointOwner.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSharePointPerms.ps1 index 542dfb665b9f..347a5e5721bd 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSharePointOwner.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSharePointPerms.ps1 @@ -1,6 +1,6 @@ using namespace System.Net -Function Invoke-ExecSharePointOwner { +Function Invoke-ExecSharePointPerms { <# .FUNCTIONALITY Entrypoint @@ -13,7 +13,7 @@ Function Invoke-ExecSharePointOwner { $APIName = $TriggerMetadata.FunctionName $tenantFilter = $Request.Body.TenantFilter try { - $State = Set-CIPPSharePointOwner -tenantFilter $tenantFilter -userid $request.body.UPN -OnedriveAccessUser $request.body.input -ExecutingUser $ExecutingUser -APIName $APIName -RemovePermission $request.body.RemovePermission -URL $Request.Body.URL + $State = Set-CIPPSharePointPerms -tenantFilter $tenantFilter -userid $request.body.UPN -OnedriveAccessUser $request.body.input -ExecutingUser $ExecutingUser -APIName $APIName -RemovePermission $request.body.RemovePermission -URL $Request.Body.URL $Results = [pscustomobject]@{'Results' = "$State" } } catch { $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAuditLogTest.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAuditLogTest.ps1 new file mode 100644 index 000000000000..34576f5b5811 --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAuditLogTest.ps1 @@ -0,0 +1,41 @@ +function Invoke-ListAuditLogTest { + <# + .FUNCTIONALITY + Entrypoint + + .ROLE + Tenant.Alert.Read + #> + Param($Request, $TriggerMetadata) + + $AuditLogQuery = @{ + TenantFilter = $Request.Query.TenantFilter + LogType = $Request.Query.LogType + ShowAll = $true + } + try { + $TestResults = Test-CIPPAuditLogRules @AuditLogQuery + } catch { + $Body = Get-CippException -Exception $_ + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::InternalServerError + Body = $Body + }) + return + } + $Body = @{ + Results = @($TestResults.DataToProcess) + Metadata = @{ + TenantFilter = $AuditLogQuery.TenantFilter + LogType = $AuditLogQuery.LogType + TotalLogs = $TestResults.TotalLogs + MatchedLogs = $TestResults.MatchedLogs + MatchedRules = $TestResults.MatchedRules + } + } + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $Body + }) + +} \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-PublicWebhooks.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-PublicWebhooks.ps1 index 78cded90ff19..3a4e60373847 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-PublicWebhooks.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-PublicWebhooks.ps1 @@ -65,165 +65,7 @@ function Invoke-PublicWebhooks { } Add-CIPPAzDataTableEntity @WebhookIncoming -Entity $Entity } else { - if ($request.headers.'x-ms-original-url' -notlike '*version=2*') { - return "Not replying to this webhook or processing it, as it's not a version 2 webhook." - } else { - try { - foreach ($ReceivedItem In $Request.body) { - $ReceivedItem = [pscustomobject]$ReceivedItem - $TenantFilter = (Get-Tenants | Where-Object -Property customerId -EQ $ReceivedItem.TenantId).defaultDomainName - Write-Host "Webhook TenantFilter: $TenantFilter" - $ConfigTable = get-cipptable -TableName 'WebhookRules' - $Configuration = (Get-CIPPAzDataTableEntity @ConfigTable) | Where-Object { ($_.Tenants -match $TenantFilter -or $_.Tenants -match 'AllTenants') -and $_.Type -eq $ReceivedItem.ContentType } | ForEach-Object { - [pscustomobject]@{ - Tenants = ($_.Tenants | ConvertFrom-Json).fullValue - Conditions = $_.Conditions - Actions = $_.Actions - LogType = $_.Type - } - } - if (!$Configuration.Tenants) { - Write-Host 'No tenants found for this webhook, probably an old entry. Skipping.' - continue - } - Write-Host "Webhook: The received content-type for $($TenantFilter) is $($ReceivedItem.ContentType)" - if ($ReceivedItem.ContentType -in $Configuration.LogType) { - $Data = New-GraphPostRequest -type GET -uri "https://manage.office.com/api/v1.0/$($ReceivedItem.tenantId)/activity/feed/audit/$($ReceivedItem.contentid)" -tenantid $TenantFilter -scope 'https://manage.office.com/.default' - } else { - Write-Host "No data to download for $($ReceivedItem.ContentType)" - continue - } - - $PreProccessedData = $Data | Select-Object *, CIPPAction, CIPPClause, CIPPGeoLocation, CIPPBadRepIP, CIPPHostedIP, CIPPIPDetected, CIPPLocationInfo, CIPPExtendedProperties, CIPPDeviceProperties, CIPPParameters, CIPPModifiedProperties -ErrorAction SilentlyContinue - $LocationTable = Get-CIPPTable -TableName 'knownlocationdb' - $ProcessedData = foreach ($Data in $PreProccessedData) { - if ($Data.ExtendedProperties) { - $Data.CIPPExtendedProperties = ($Data.ExtendedProperties | ConvertTo-Json) - $Data.ExtendedProperties | ForEach-Object { $data | Add-Member -NotePropertyName $_.Name -NotePropertyValue $_.Value -Force -ErrorAction SilentlyContinue } - } - if ($Data.DeviceProperties) { - $Data.CIPPDeviceProperties = ($Data.DeviceProperties | ConvertTo-Json) - $Data.DeviceProperties | ForEach-Object { $data | Add-Member -NotePropertyName $_.Name -NotePropertyValue $_.Value -Force -ErrorAction SilentlyContinue } - } - if ($Data.parameters) { - $Data.CIPPParameters = ($Data.parameters | ConvertTo-Json) - $Data.parameters | ForEach-Object { $data | Add-Member -NotePropertyName $_.Name -NotePropertyValue $_.Value -Force -ErrorAction SilentlyContinue } - } - if ($Data.ModifiedProperties) { - $Data.CIPPModifiedProperties = ($Data.ModifiedProperties | ConvertTo-Json) - $Data.ModifiedProperties | ForEach-Object { $data | Add-Member -NotePropertyName "$($_.Name)" -NotePropertyValue "$($_.NewValue)" -Force -ErrorAction SilentlyContinue } - } - if ($Data.ModifiedProperties) { $Data.ModifiedProperties | ForEach-Object { $data | Add-Member -NotePropertyName $("Previous_Value_$($_.Name)") -NotePropertyValue "$($_.OldValue)" -Force -ErrorAction SilentlyContinue } } - - if ($data.clientip) { - if ($data.clientip -match '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+$') { - $data.clientip = $data.clientip -replace ':\d+$', '' # Remove the port number if present - } - $Location = Get-CIPPAzDataTableEntity @LocationTable -Filter "RowKey eq '$($data.clientIp)'" | Select-Object -Last 1 - if ($Location) { - Write-Host 'Webhook: Got IP from cache' - $Country = $Location.CountryOrRegion - $City = $Location.City - $Proxy = $Location.Proxy - $hosting = $Location.Hosting - $ASName = $Location.ASName - } else { - Write-Host 'Webhook: We have to do a lookup' - $Location = Get-CIPPGeoIPLocation -IP $data.clientip - $Country = if ($Location.CountryCode) { $Location.CountryCode } else { 'Unknown' } - $City = if ($Location.City) { $Location.City } else { 'Unknown' } - $Proxy = if ($Location.Proxy -ne $null) { $Location.Proxy } else { 'Unknown' } - $hosting = if ($Location.Hosting -ne $null) { $Location.Hosting } else { 'Unknown' } - $ASName = if ($Location.ASName) { $Location.ASName } else { 'Unknown' } - $IP = $data.ClientIP - $LocationInfo = @{ - RowKey = [string]$data.clientip - PartitionKey = [string]$data.id - Tenant = [string]$TenantFilter - CountryOrRegion = "$Country" - City = "$City" - Proxy = "$Proxy" - Hosting = "$hosting" - ASName = "$ASName" - } - try { - $null = Add-CIPPAzDataTableEntity @LocationTable -Entity $LocationInfo -Force - } catch { - Write-Host "Webhook: Failed to add location info for $($data.clientip) to cache: $($_.Exception.Message)" - - } - } - $Data.CIPPGeoLocation = $Country - $Data.CIPPBadRepIP = $Proxy - $Data.CIPPHostedIP = $hosting - $Data.CIPPIPDetected = $IP - $Data.CIPPLocationInfo = ($Location | ConvertTo-Json) - } - $Data | Select-Object * -ExcludeProperty ExtendedProperties, DeviceProperties, parameters - } - - #Filter data based on conditions. - $Where = $Configuration | ForEach-Object { - $conditions = $_.Conditions | ConvertFrom-Json | Where-Object { $_.Input.value -ne '' } - $actions = $_.Actions - $conditionStrings = [System.Collections.Generic.List[string]]::new() - $CIPPClause = [System.Collections.Generic.List[string]]::new() - foreach ($condition in $conditions) { - $value = if ($condition.Input.value -is [array]) { - $arrayAsString = $condition.Input.value | ForEach-Object { - "'$_'" - } - "@($($arrayAsString -join ', '))" - } else { "'$($condition.Input.value)'" } - - $conditionStrings.Add("`$(`$_.$($condition.Property.label)) -$($condition.Operator.value) $value") - $CIPPClause.Add("$($condition.Property.label) is $($condition.Operator.label) $value") - } - $finalCondition = $conditionStrings -join ' -AND ' - - [PSCustomObject]@{ - clause = $finalCondition - expectedAction = $actions - CIPPClause = $CIPPClause - } - - } - Write-Host "Webhook: The list of operations in the data are $($ProcessedData.operation -join ', ')" - - $DataToProcess = foreach ($clause in $Where) { - Write-Host "Webhook: Processing clause: $($clause.clause)" - Write-Host "Webhook: If this clause would be true, the action would be: $($clause.expectedAction)" - $ReturnedData = $ProcessedData | Where-Object { Invoke-Expression $clause.clause } - if ($ReturnedData) { - $ReturnedData = foreach ($item in $ReturnedData) { - $item.CIPPAction = $clause.expectedAction - $item.CIPPClause = $clause.CIPPClause -join ' and ' - $item - } - } - $ReturnedData - } - - Write-Host "Webhook: Data to process found: $($DataToProcess.count) items" - foreach ($Item in $DataToProcess) { - Write-Host "Processing $($item.operation)" - ## Push webhook data to table - $Entity = [PSCustomObject]@{ - PartitionKey = 'Webhook' - RowKey = [string]$item.id - Type = 'AuditLog' - Data = [string]($Item | ConvertTo-Json -Depth 10) - CIPPURL = $CIPPURL - TenantFilter = $TenantFilter - FunctionName = 'PublicWebhookProcess' - } - Add-CIPPAzDataTableEntity @WebhookIncoming -Entity $Entity -Force - } - } - } catch { - Write-Host "Webhook Failed: $($_.Exception.Message). Line number $($_.InvocationInfo.ScriptLineNumber)" - } - } + return 'Not replying to this webhook or processing it' } $Body = 'Webhook Recieved' $StatusCode = [HttpStatusCode]::OK diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListDomainAnalyser.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListDomainAnalyser.ps1 index 95077930211f..3d85e4747122 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListDomainAnalyser.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListDomainAnalyser.ps1 @@ -11,7 +11,7 @@ Function Invoke-ListDomainAnalyser { [CmdletBinding()] param($Request, $TriggerMetadata) - $Results = Get-CIPPDomainAnalyser -TenantFilter $Request.query.tenantFilter + $Results = Get-CIPPDomainAnalyser -TenantFilter $Request.Query.tenantFilter # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCalendarPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCalendarPermissions.ps1 index 9112981dad14..fbbe6c93bdd2 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCalendarPermissions.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCalendarPermissions.ps1 @@ -17,9 +17,9 @@ Function Invoke-ListCalendarPermissions { try { $GetCalParam = @{Identity = $UserID; FolderScope = 'Calendar' } - $CalendarFolder = New-ExoRequest -tenantid $Tenantfilter -cmdlet 'Get-MailboxFolderStatistics' -cmdParams $GetCalParam | Select-Object -First 1 + $CalendarFolder = New-ExoRequest -tenantid $Tenantfilter -cmdlet 'Get-MailboxFolderStatistics' -anchor $UserID -cmdParams $GetCalParam | Select-Object -First 1 $CalParam = @{Identity = "$($UserID):\$($CalendarFolder.name)" } - $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet 'Get-MailboxFolderPermission' -cmdParams $CalParam -UseSystemMailbox $true | Select-Object Identity, User, AccessRights, FolderName + $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet 'Get-MailboxFolderPermission' -anchor $UserID -cmdParams $CalParam -UseSystemMailbox $true | Select-Object Identity, User, AccessRights, FolderName Write-LogMessage -API 'List Calendar Permissions' -tenant $tenantfilter -message "Calendar permissions listed for $($tenantfilter)" -sev Debug $StatusCode = [HttpStatusCode]::OK } catch { diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharepointQuota.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharepointQuota.ps1 index b8d7d8a50995..21d521629abc 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharepointQuota.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharepointQuota.ps1 @@ -23,7 +23,7 @@ Function Invoke-ListSharepointQuota { $UsedStoragePercentage = 'Not Supported' } else { 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' -tenantid $TenantFilter).id.Split('.')[0] $sharepointToken = (Get-GraphToken -scope "https://$($tenantName)-admin.sharepoint.com/.default" -tenantid $TenantFilter) $sharepointToken.Add('accept', 'application/json') diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSignIns.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSignIns.ps1 index b58f472a7494..5547efe9cfd2 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSignIns.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSignIns.ps1 @@ -16,27 +16,32 @@ Function Invoke-ListSignIns { Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' # Interact with query parameters or the body of the request. $TenantFilter = $Request.Query.TenantFilter + $Days = $Request.Query.Days ?? 7 + try { - if ($Request.query.failedlogonOnly) { + if ($Request.Query.failedLogonsOnly) { $FailedLogons = ' and (status/errorCode eq 50126)' } - $filters = if ($Request.query.Filter) { - $request.query.filter + $filters = if ($Request.Query.Filter) { + $Request.Query.filter } else { - $currentTime = Get-Date -Format 'yyyy-MM-dd' - $ts = (Get-Date).AddDays(-7) + $ts = (Get-Date).AddDays(-$Days).ToUniversalTime() $endTime = $ts.ToString('yyyy-MM-dd') - "createdDateTime ge $($endTime) and createdDateTime lt $($currentTime) and userDisplayName ne 'On-Premises Directory Synchronization Service Account' $FailedLogons" + "createdDateTime ge $($endTime) and userDisplayName ne 'On-Premises Directory Synchronization Service Account' $FailedLogons" } Write-Host $Filters + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Retrieved sign in report' -Sev 'Debug' -tenant $TenantFilter $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/auditLogs/signIns?api-version=beta&`$filter=$($filters)" -tenantid $TenantFilter -erroraction stop $response = $GraphRequest | Select-Object *, @{l = 'additionalDetails'; e = { $_.status.additionalDetails } } , @{l = 'errorCode'; e = { $_.status.errorCode } }, @{l = 'locationcipp'; e = { "$($_.location.city) - $($_.location.countryOrRegion)" } } - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Retrieved sign in report' -Sev 'Debug' -tenant $TenantFilter + + if ($Request.Query.failedLogonsOnly -and $Request.Query.FailureThreshold -and $Request.Query.FailureThreshold -gt 0) { + $response = $response | Group-Object -Property userPrincipalName | Where-Object { $_.Count -ge $Request.Query.FailureThreshold } | Select-Object -ExpandProperty Group + } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ diff --git a/Modules/CIPPCore/Public/Get-SlackAlertBlocks.ps1 b/Modules/CIPPCore/Public/Get-SlackAlertBlocks.ps1 index b59ce99a3160..60e42aee5ced 100644 --- a/Modules/CIPPCore/Public/Get-SlackAlertBlocks.ps1 +++ b/Modules/CIPPCore/Public/Get-SlackAlertBlocks.ps1 @@ -151,7 +151,7 @@ function Get-SlackAlertBlocks { $Fields = [system.collections.generic.list[object]]::new() foreach ($Key in $Payload.RawData.PSObject.Properties.Name) { # if value is json continue to next property - if ($Payload.RawData.$Key -is [string] -and ![string]::IsNullOrEmpty($Payload.RawData.$Key)) { + if ($Payload.RawData.$Key -is [string] -and ([string]::IsNullOrEmpty($Payload.RawData.$Key) -or (Test-Json $Payload.RawData.$Key -ErrorAction SilentlyContinue))) { continue } # if value is date object @@ -187,13 +187,14 @@ function Get-SlackAlertBlocks { }) } elseif (Test-Json $Payload.RawData.$Key.$SubKey -ErrorAction SilentlyContinue) { # parse json and iterate through properties - $SubKeyData = $Payload.RawData.$Key.$SubKey | ConvertFrom-Json + continue + <#$SubKeyData = $Payload.RawData.$Key.$SubKey | ConvertFrom-Json foreach ($SubSubKey in $SubKeyData.PSObject.Properties.Name) { $Fields.Add(@{ type = 'mrkdwn' text = "*$($Key)/$($SubKey)/$($SubSubKey):*`n" + $SubKeyData.$SubSubKey }) - } + }#> } else { $Fields.Add(@{ type = 'mrkdwn' diff --git a/Modules/CIPPCore/Public/GraphHelper/Get-NormalizedError.ps1 b/Modules/CIPPCore/Public/GraphHelper/Get-NormalizedError.ps1 index 42bdbfcd5356..46f092f6aff3 100644 --- a/Modules/CIPPCore/Public/GraphHelper/Get-NormalizedError.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/Get-NormalizedError.ps1 @@ -1,63 +1,64 @@ -function Get-NormalizedError { - <# - .FUNCTIONALITY - Internal - #> - [CmdletBinding()] - param ( - [string]$message - ) - - #Check if the message is valid JSON. - try { - $JSONMsg = $message | ConvertFrom-Json - } catch { - } - #if the message is valid JSON, there can be multiple fields in which the error resides. These are: - # $message.error.Innererror.Message - # $message.error.Message - # $message.error.details.message - # $message.error.innererror.internalException.message - - #We need to check if the message is in one of these fields, and if so, return it. - if ($JSONMsg.error.innererror.message) { - Write-Host 'innererror.message found' - $message = $JSONMsg.error.innererror.message - } elseif ($JSONMsg.error.message) { - Write-Host 'error.message found' - $message = $JSONMsg.error.message - } elseif ($JSONMsg.error.details.message) { - Write-Host 'error.details.message found' - $message = $JSONMsg.error.details.message - } elseif ($JSONMsg.error.innererror.internalException.message) { - Write-Host 'error.innererror.internalException.message found' - $message = $JSONMsg.error.innererror.internalException.message - } - - - #finally, put the message through the translator. If it's not in the list, just return the original message - switch -Wildcard ($message) { - 'Request not applicable to target tenant.' { 'Required license not available for this tenant' } - "Neither tenant is B2C or tenant doesn't have premium license" { 'This feature requires a P1 license or higher' } - 'Response status code does not indicate success: 400 (Bad Request).' { 'Error 400 occured. There is an issue with the token configuration for this tenant. Please perform an access check' } - '*Microsoft.Skype.Sync.Pstn.Tnm.Common.Http.HttpResponseException*' { 'Could not connect to Teams Admin center - Tenant might be missing a Teams license' } - '*Provide valid credential.*' { 'Error 400: There is an issue with your Exchange Token configuration. Please perform an access check for this tenant' } - '*This indicate that a subscription within the tenant has lapsed*' { 'There is subscription for this service available, Check licensing information.' } - '*User was not found.*' { 'The relationship between this tenant and the partner has been dissolved from the tenant side.' } - '*The user or administrator has not consented to use the application*' { 'CIPP cannot access this tenant. Perform a CPV Refresh and Access Check via the settings menu' } - '*AADSTS50020*' { 'AADSTS50020: The user you have used for your Secure Application Model is a guest in this tenant, or your are using GDAP and have not added the user to the correct group. Please delete the guest user to gain access to this tenant' } - '*AADSTS50177' { 'AADSTS50177: The user you have used for your Secure Application Model is a guest in this tenant, or your are using GDAP and have not added the user to the correct group. Please delete the guest user to gain access to this tenant' } - '*invalid or malformed*' { 'The request is malformed. Have you finished the SAM Setup?' } - '*Windows Store repository apps feature is not supported for this tenant*' { 'This tenant does not have WinGet support available' } - '*AADSTS650051*' { 'The application does not exist yet. Try again in 30 seconds.' } - '*AppLifecycle_2210*' { 'Failed to call Intune APIs: Does the tenant have a license available?' } - '*One or more added object references already exist for the following modified properties:*' { 'This user is already a member of this group.' } - '*Microsoft.Exchange.Management.Tasks.MemberAlreadyExistsException*' { 'This user is already a member of this group.' } - '*The property value exceeds the maximum allowed size (64KB)*' { 'One of the values exceeds the maximum allowed size (64KB).' } - '*Unable to initialize the authorization context*' { 'Your GDAP configuration does not allow us to write to this tenant, please check your group mappings and tenant onboarding.' } - '*Providers.Common.V1.CoreException*' { '403 (Access Denied) - We cannot connect to this tenant.' } - '*Authentication failed. MFA required*' { 'Authentication failed. MFA required' } - Default { $message } - - } -} +function Get-NormalizedError { + <# + .FUNCTIONALITY + Internal + #> + [CmdletBinding()] + param ( + [string]$message + ) + + #Check if the message is valid JSON. + try { + $JSONMsg = $message | ConvertFrom-Json + } catch { + } + #if the message is valid JSON, there can be multiple fields in which the error resides. These are: + # $message.error.Innererror.Message + # $message.error.Message + # $message.error.details.message + # $message.error.innererror.internalException.message + + #We need to check if the message is in one of these fields, and if so, return it. + if ($JSONMsg.error.innererror.message) { + Write-Host 'innererror.message found' + $message = $JSONMsg.error.innererror.message + } elseif ($JSONMsg.error.message) { + Write-Host 'error.message found' + $message = $JSONMsg.error.message + } elseif ($JSONMsg.error.details.message) { + Write-Host 'error.details.message found' + $message = $JSONMsg.error.details.message + } elseif ($JSONMsg.error.innererror.internalException.message) { + Write-Host 'error.innererror.internalException.message found' + $message = $JSONMsg.error.innererror.internalException.message + } + + + #finally, put the message through the translator. If it's not in the list, just return the original message + switch -Wildcard ($message) { + 'Request not applicable to target tenant.' { 'Required license not available for this tenant' } + "Neither tenant is B2C or tenant doesn't have premium license" { 'This feature requires a P1 license or higher' } + 'Response status code does not indicate success: 400 (Bad Request).' { 'Error 400 occured. There is an issue with the token configuration for this tenant. Please perform an access check' } + '*Microsoft.Skype.Sync.Pstn.Tnm.Common.Http.HttpResponseException*' { 'Could not connect to Teams Admin center - Tenant might be missing a Teams license' } + '*Provide valid credential.*' { 'Error 400: There is an issue with your Exchange Token configuration. Please perform an access check for this tenant' } + '*This indicate that a subscription within the tenant has lapsed*' { 'There is subscription for this service available, Check licensing information.' } + '*User was not found.*' { 'The relationship between this tenant and the partner has been dissolved from the tenant side.' } + '*The user or administrator has not consented to use the application*' { 'CIPP cannot access this tenant. Perform a CPV Refresh and Access Check via the settings menu' } + '*AADSTS50020*' { 'AADSTS50020: The user you have used for your Secure Application Model is a guest in this tenant, or your are using GDAP and have not added the user to the correct group. Please delete the guest user to gain access to this tenant' } + '*AADSTS50177' { 'AADSTS50177: The user you have used for your Secure Application Model is a guest in this tenant, or your are using GDAP and have not added the user to the correct group. Please delete the guest user to gain access to this tenant' } + '*invalid or malformed*' { 'The request is malformed. Have you finished the SAM Setup?' } + '*Windows Store repository apps feature is not supported for this tenant*' { 'This tenant does not have WinGet support available' } + '*AADSTS650051*' { 'The application does not exist yet. Try again in 30 seconds.' } + '*AppLifecycle_2210*' { 'Failed to call Intune APIs: Does the tenant have a license available?' } + '*One or more added object references already exist for the following modified properties:*' { 'This user is already a member of this group.' } + '*Microsoft.Exchange.Management.Tasks.MemberAlreadyExistsException*' { 'This user is already a member of this group.' } + '*The property value exceeds the maximum allowed size (64KB)*' { 'One of the values exceeds the maximum allowed size (64KB).' } + '*Unable to initialize the authorization context*' { 'Your GDAP configuration does not allow us to write to this tenant, please check your group mappings and tenant onboarding.' } + '*Providers.Common.V1.CoreException*' { '403 (Access Denied) - We cannot connect to this tenant.' } + '*Authentication failed. MFA required*' { 'Authentication failed. MFA required' } + '*Your tenant is not licensed for this feature.*' { 'Required license not available for this tenant' } + Default { $message } + + } +} diff --git a/Modules/CIPPCore/Public/GraphHelper/Get-Tenants.ps1 b/Modules/CIPPCore/Public/GraphHelper/Get-Tenants.ps1 index fdcb3d3eb95b..fc635a188857 100644 --- a/Modules/CIPPCore/Public/GraphHelper/Get-Tenants.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/Get-Tenants.ps1 @@ -67,7 +67,7 @@ function Get-Tenants { $ActiveRelationships = $GDAPList | Where-Object { $_.customerId -notin $SkipListCache.customerId } $TenantList = $ActiveRelationships | Group-Object -Property customerId | ForEach-Object { - Write-Host "Processing $($_.Name) to add to tenant list." + #Write-Host "Processing $($_.Name) to add to tenant list." $ExistingTenantInfo = Get-CIPPAzDataTableEntity @TenantsTable -Filter "PartitionKey eq 'Tenants' and RowKey eq '$($_.Name)'" if ($TriggerRefresh.IsPresent -and $ExistingTenantInfo.customerId) { @@ -77,7 +77,7 @@ function Get-Tenants { } if ($ExistingTenantInfo -and $ExistingTenantInfo.RequiresRefresh -eq $false) { - Write-Host 'Existing tenant found. We already have it cached, skipping.' + #Write-Host 'Existing tenant found. We already have it cached, skipping.' $ExistingTenantInfo return } @@ -86,7 +86,7 @@ function Get-Tenants { if (-not $SkipDomains.IsPresent) { try { - Write-Host "Getting domains for $($_.Name)." + #Write-Host "Getting domains for $($_.Name)." $Domains = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/domains?$top=999' -tenantid $LatestRelationship.customerId -NoAuthCheck:$true -ErrorAction Stop $defaultDomainName = ($Domains | Where-Object { $_.isDefault -eq $true }).id $initialDomainName = ($Domains | Where-Object { $_.isInitial -eq $true }).id diff --git a/Modules/CIPPCore/Public/GraphHelper/New-GraphGetRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-GraphGetRequest.ps1 index 65a5edca23f2..7c4eb8927b35 100644 --- a/Modules/CIPPCore/Public/GraphHelper/New-GraphGetRequest.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/New-GraphGetRequest.ps1 @@ -12,7 +12,8 @@ function New-GraphGetRequest { $NoAuthCheck, $skipTokenCache, [switch]$ComplexFilter, - [switch]$CountOnly + [switch]$CountOnly, + [switch]$IncludeResponseHeaders ) if ($NoAuthCheck -or (Get-AuthorisedRequest -Uri $uri -TenantID $tenantid)) { @@ -43,13 +44,35 @@ function New-GraphGetRequest { $ReturnedData = do { try { - $Data = (Invoke-RestMethod -Uri $nextURL -Method GET -Headers $headers -ContentType 'application/json; charset=utf-8') + $GraphRequest = @{ + Uri = $nextURL + Method = 'GET' + Headers = $headers + ContentType = 'application/json; charset=utf-8' + } + if ($IncludeResponseHeaders) { + $GraphRequest.ResponseHeadersVariable = 'ResponseHeaders' + } + $Data = (Invoke-RestMethod @GraphRequest) if ($CountOnly) { $Data.'@odata.count' - $nextURL = $null + $NextURL = $null } else { - if ($data.value) { $data.value } else { ($Data) } - if ($noPagination) { $nextURL = $null } else { $nextURL = $data.'@odata.nextLink' } + if ($Data.PSObject.Properties.Name -contains 'value') { $data.value } else { ($Data) } + if ($noPagination) { + $nextURL = $null + } else { + $NextPageUriFound = $false + if ($IncludeResponseHeaders) { + if ($ResponseHeaders.NextPageUri) { + $NextURL = $ResponseHeaders.NextPageUri + $NextPageUriFound = $true + } + } + if (!$NextPageUriFound) { + $nextURL = $data.'@odata.nextLink' + } + } } } catch { try { @@ -63,7 +86,7 @@ function New-GraphGetRequest { } throw $Message } - } until ($null -eq $NextURL -or ' ' -eq $NextURL) + } until ([string]::IsNullOrEmpty($NextURL) -or $NextURL -is [object[]] -or ' ' -eq $NextURL) $Tenant.LastGraphError = '' Update-AzDataTableEntity @TenantsTable -Entity $Tenant return $ReturnedData diff --git a/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 b/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 index 533d0954679a..e051a2a0144b 100644 --- a/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 +++ b/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 @@ -36,7 +36,7 @@ function Invoke-CIPPOffboardingJob { } { $_.'OnedriveAccess' -ne '' } { - $Options.OnedriveAccess | ForEach-Object { Set-CIPPSharePointOwner -tenantFilter $tenantFilter -userid $username -OnedriveAccessUser $_.value -ExecutingUser $ExecutingUser -APIName $APIName } + $Options.OnedriveAccess | ForEach-Object { Set-CIPPSharePointPerms -tenantFilter $tenantFilter -userid $username -OnedriveAccessUser $_.value -ExecutingUser $ExecutingUser -APIName $APIName } } { $_.'AccessNoAutomap' -ne '' } { diff --git a/Modules/CIPPCore/Public/Invoke-RemoveSpamfilter.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveSpamfilter.ps1 index 55f525aa36f2..d1d0160aaa34 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveSpamfilter.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveSpamfilter.ps1 @@ -20,9 +20,9 @@ Function Invoke-RemoveSpamfilter { try { $cmdlet = 'Remove-HostedContentFilterRule' - $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet $cmdlet -cmdParams $params -useSystemmailbox $true + $null = New-ExoRequest -tenantid $Tenantfilter -cmdlet $cmdlet -cmdParams $params -useSystemmailbox $true $cmdlet = 'Remove-HostedContentFilterPolicy' - $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet $cmdlet -cmdParams $params -useSystemmailbox $true + $null = New-ExoRequest -tenantid $Tenantfilter -cmdlet $cmdlet -cmdParams $params -useSystemmailbox $true $Result = "Deleted $($Request.query.name)" Write-LogMessage -API 'TransportRules' -tenant $tenantfilter -message "Deleted transport rule $($Request.query.name)" -sev Debug } catch { diff --git a/Modules/CIPPCore/Public/Invoke-RemoveTransportRule.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveTransportRule.ps1 index 3a86c418314d..aa358ad25202 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveTransportRule.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveTransportRule.ps1 @@ -21,7 +21,7 @@ Function Invoke-RemoveTransportRule { try { $cmdlet = 'Remove-TransportRule' - $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet $cmdlet -cmdParams $params -UseSystemMailbox $true + $null = New-ExoRequest -tenantid $Tenantfilter -cmdlet $cmdlet -cmdParams $params -UseSystemMailbox $true $Result = "Deleted $($Request.query.guid)" Write-LogMessage -API 'TransportRules' -tenant $tenantfilter -message "Deleted transport rule $($Request.query.guid)" -sev Debug } catch { diff --git a/Modules/CIPPCore/Public/SAMManifest.json b/Modules/CIPPCore/Public/SAMManifest.json index b6b291da57b4..427d2f98fe0c 100644 --- a/Modules/CIPPCore/Public/SAMManifest.json +++ b/Modules/CIPPCore/Public/SAMManifest.json @@ -1,206 +1,210 @@ -{ - "isFallbackPublicClient": true, - "signInAudience": "AzureADMultipleOrgs", - "displayName": "CIPP-SAM", - "web": { - "redirectUris": [ - "https://login.microsoftonline.com/common/oauth2/nativeclient", - "https://localhost", - "http://localhost", - "http://localhost:8400" - ] - }, - "requiredResourceAccess": [ - { - "resourceAppId": "fa3d9a0c-3fb0-42cc-9193-47c7ecd2edbd", - "resourceAccess": [ - { "id": "1cebfa2a-fb4d-419e-b5f9-839b4383e05a", "type": "Scope" } - ] - }, - { - "resourceAppId": "00000003-0000-0000-c000-000000000000", - "resourceAccess": [ - { "id": "aa07f155-3612-49b8-a147-6c590df35536", "type": "Scope" }, - { "id": "0f4595f7-64b1-4e13-81bc-11a249df07a9", "type": "Scope" }, - { "id": "73e75199-7c3e-41bb-9357-167164dbb415", "type": "Scope" }, - { "id": "7ab1d787-bae7-4d5d-8db6-37ea32df9186", "type": "Scope" }, - { "id": "d01b97e9-cbc0-49fe-810a-750afd5527a3", "type": "Scope" }, - { "id": "46ca0847-7e6b-426e-9775-ea810a948356", "type": "Scope" }, - { "id": "dc38509c-b87d-4da0-bd92-6bec988bac4a", "type": "Scope" }, - { "id": "7427e0e9-2fba-42fe-b0c0-848c9e6a8182", "type": "Scope" }, - { "id": "ad902697-1014-4ef5-81ef-2b4301988e8c", "type": "Scope" }, - { "id": "572fea84-0151-49b2-9301-11cb16974376", "type": "Scope" }, - { "id": "e4c9e354-4dc5-45b8-9e7c-e1393b0b1a20", "type": "Scope" }, - { "id": "0883f392-0a7a-443d-8c76-16a6d39c7b63", "type": "Scope" }, - { "id": "7b3f05d5-f68c-4b8d-8c59-a2ecd12f24af", "type": "Scope" }, - { "id": "0c5e8a55-87a6-4556-93ab-adc52c4d862d", "type": "Scope" }, - { "id": "44642bfe-8385-4adc-8fc6-fe3cb2c375c3", "type": "Scope" }, - { "id": "662ed50a-ac44-4eef-ad86-62eed9be2a29", "type": "Scope" }, - { "id": "8696daa5-bce5-4b2e-83f9-51b6defc4e1e", "type": "Scope" }, - { "id": "6aedf524-7e1c-45a7-bd76-ded8cab8d0fc", "type": "Scope" }, - { "id": "bac3b9c2-b516-4ef4-bd3b-c2ef73d8d804", "type": "Scope" }, - { "id": "11d4cd79-5ba5-460f-803f-e22c8ab85ccd", "type": "Scope" }, - { "id": "02e97553-ed7b-43d0-ab3c-f8bace0d040c", "type": "Scope" }, - { "id": "89fe6a52-be36-487e-b7d8-d061c450a026", "type": "Scope" }, - { "id": "a367ab51-6b49-43bf-a716-a1fb06d2a174", "type": "Scope" }, - { "id": "204e0828-b5ca-4ad8-b9f3-f32a958e7cc4", "type": "Scope" }, - { "id": "4e46008b-f24c-477d-8fff-7bb4ec7aafe0", "type": "Scope" }, - { "id": "0e263e50-5827-48a4-b97c-d940288653c7", "type": "Scope" }, - { "id": "e383f46e-2787-4529-855e-0e479a3ffac0", "type": "Scope" }, - { "id": "37f7f235-527c-4136-accd-4a02d197296e", "type": "Scope" }, - { "id": "14dad69e-099b-42c9-810b-d002981feec1", "type": "Scope" }, - { "id": "f6a3db3e-f7e8-4ed2-a414-557c8c9830be", "type": "Scope" }, - { "id": "0e755559-83fb-4b44-91d0-4cc721b9323e", "type": "Scope" }, - { "id": "a84a9652-ffd3-496e-a991-22ba5529156a", "type": "Scope" }, - { "id": "1d89d70c-dcac-4248-b214-903c457af83a", "type": "Scope" }, - { "id": "2b61aa8a-6d36-4b2f-ac7b-f29867937c53", "type": "Scope" }, - { "id": "ebf0f66e-9fb1-49e4-a278-222f76911cf4", "type": "Scope" }, - { "id": "c79f8feb-a9db-4090-85f9-90d820caa0eb", "type": "Scope" }, - { "id": "bdfbf15f-ee85-4955-8675-146e8e5296b5", "type": "Scope" }, - { "id": "f81125ac-d3b7-4573-a3b2-7099cc39df9e", "type": "Scope" }, - { "id": "cac97e40-6730-457d-ad8d-4852fddab7ad", "type": "Scope" }, - { "id": "b7887744-6746-4312-813d-72daeaee7e2d", "type": "Scope" }, - { "id": "48971fc1-70d7-4245-af77-0beb29b53ee2", "type": "Scope" }, - { "id": "aec28ec7-4d02-4e8c-b864-50163aea77eb", "type": "Scope" }, - { "id": "a9ff19c2-f369-4a95-9a25-ba9d460efc8e", "type": "Scope" }, - { "id": "59dacb05-e88d-4c13-a684-59f1afc8cc98", "type": "Scope" }, - { "id": "b98bfd41-87c6-45cc-b104-e2de4f0dafb9", "type": "Scope" }, - { "id": "2f9ee017-59c1-4f1d-9472-bd5529a7b311", "type": "Scope" }, - { "id": "951183d1-1a61-466f-a6d1-1fde911bfd95", "type": "Scope" }, - { "id": "637d7bec-b31e-4deb-acc9-24275642a2c9", "type": "Scope" }, - { "id": "101147cf-4178-4455-9d58-02b5c164e759", "type": "Scope" }, - { "id": "cc83893a-e232-4723-b5af-bd0b01bcfe65", "type": "Scope" }, - { "id": "233e0cf1-dd62-48bc-b65b-b38fe87fcf8e", "type": "Scope" }, - { "id": "d649fb7c-72b4-4eec-b2b4-b15acf79e378", "type": "Scope" }, - { "id": "485be79e-c497-4b35-9400-0e3fa7f2a5d4", "type": "Scope" }, - { "id": "9d8982ae-4365-4f57-95e9-d6032a4c0b87", "type": "Scope" }, - { "id": "48638b3c-ad68-4383-8ac4-e6880ee6ca57", "type": "Scope" }, - { "id": "39d65650-9d3e-4223-80db-a335590d027e", "type": "Scope" }, - { "id": "4a06efd2-f825-4e34-813e-82a57b03d1ee", "type": "Scope" }, - { "id": "f3bfad56-966e-4590-a536-82ecf548ac1e", "type": "Scope" }, - { "id": "4d135e65-66b8-41a8-9f8b-081452c91774", "type": "Scope" }, - { "id": "2eadaff8-0bce-4198-a6b9-2cfc35a30075", "type": "Scope" }, - { "id": "0c3e411a-ce45-4cd1-8f30-f99a3efa7b11", "type": "Scope" }, - { "id": "edb72de9-4252-4d03-a925-451deef99db7", "type": "Scope" }, - { "id": "767156cb-16ae-4d10-8f8b-41b657c8c8c8", "type": "Scope" }, - { "id": "7e823077-d88e-468f-a337-e18f1f0e6c7c", "type": "Scope" }, - { "id": "edd3c878-b384-41fd-95ad-e7407dd775be", "type": "Scope" }, - { "id": "40b534c3-9552-4550-901b-23879c90bcf9", "type": "Scope" }, - { "id": "bf3fbf03-f35f-4e93-963e-47e4d874c37a", "type": "Scope" }, - { "id": "5248dcb1-f83b-4ec3-9f4d-a4428a961a72", "type": "Scope" }, - { "id": "c395395c-ff9a-4dba-bc1f-8372ba9dca84", "type": "Scope" }, - { "id": "2e25a044-2580-450d-8859-42eeb6e996c0", "type": "Scope" }, - { "id": "0ce33576-30e8-43b7-99e5-62f8569a4002", "type": "Scope" }, - { "id": "207e0cb1-3ce7-4922-b991-5a760c346ebc", "type": "Scope" }, - { "id": "093f8818-d05f-49b8-95bc-9d2a73e9a43c", "type": "Scope" }, - { "id": "7825d5d6-6049-4ce7-bdf6-3b8d53f4bcd0", "type": "Scope" }, - { "id": "2104a4db-3a2f-4ea0-9dba-143d457dc666", "type": "Scope" }, - { "id": "eda39fa6-f8cf-4c3c-a909-432c683e4c9b", "type": "Scope" }, - { "id": "55896846-df78-47a7-aa94-8d3d4442ca7f", "type": "Scope" }, - { "id": "aa85bf13-d771-4d5d-a9e6-bca04ce44edf", "type": "Scope" }, - { "id": "ee928332-e9c2-4747-b4a0-f8c164b68de6", "type": "Scope" }, - { "id": "c975dd04-a06e-4fbb-9704-62daad77bb49", "type": "Scope" }, - { "id": "c37c9b61-7762-4bff-a156-afc0005847a0", "type": "Scope" }, - { "id": "b9abcc4f-94fc-4457-9141-d20ce80ec952", "type": "Scope" }, - { "id": "128ca929-1a19-45e6-a3b8-435ec44a36ba", "type": "Scope" }, - { "id": "b27add92-efb2-4f16-84f5-8108ba77985c", "type": "Scope" }, - { "id": "3404d2bf-2b13-457e-a330-c24615765193", "type": "Scope" }, - { "id": "b955410e-7715-4a88-a940-dfd551018df3", "type": "Scope" }, - { "id": "5b07b0dd-2377-4e44-a38d-703f09a0dc3c", "type": "Role" }, - { "id": "19b94e34-907c-4f43-bde9-38b1909ed408", "type": "Role" }, - { "id": "999f8c63-0a38-4f1b-91fd-ed1947bdd1a9", "type": "Role" }, - { "id": "292d869f-3427-49a8-9dab-8c70152b74e9", "type": "Role" }, - { "id": "2f51be20-0bb4-4fed-bf7b-db946066c75e", "type": "Role" }, - { "id": "58ca0d9a-1575-47e1-a3cb-007ef2e4583b", "type": "Role" }, - { "id": "06a5fe6d-c49d-46a7-b082-56b1b14103c7", "type": "Role" }, - { "id": "246dd0d5-5bd0-4def-940b-0421030a5b68", "type": "Role" }, - { "id": "bf394140-e372-4bf9-a898-299cfc7564e5", "type": "Role" }, - { "id": "741f803b-c850-494e-b5df-cde7c675a1ca", "type": "Role" }, - { "id": "230c1aed-a721-4c5d-9cb4-a90514e508ef", "type": "Role" }, - { "id": "b633e1c5-b582-4048-a93e-9f11b44c7e96", "type": "Role" }, - { "id": "5b567255-7703-4780-807c-7be8301ae99b", "type": "Role" }, - { "id": "62a82d76-70ea-41e2-9197-370581804d09", "type": "Role" }, - { "id": "7ab1d382-f21e-4acd-a863-ba3e13f7da61", "type": "Role" }, - { "id": "1138cb37-bd11-4084-a2b7-9f71582aeddb", "type": "Role" }, - { "id": "78145de6-330d-4800-a6ce-494ff2d33d07", "type": "Role" }, - { "id": "9241abd9-d0e6-425a-bd4f-47ba86e767a4", "type": "Role" }, - { "id": "5b07b0dd-2377-4e44-a38d-703f09a0dc3c", "type": "Role" }, - { "id": "243333ab-4d21-40cb-a475-36241daa0842", "type": "Role" }, - { "id": "e330c4f0-4170-414e-a55a-2f022ec2b57b", "type": "Role" }, - { "id": "5ac13192-7ace-4fcf-b828-1a26f28068ee", "type": "Role" }, - { "id": "2f6817f8-7b12-4f0f-bc18-eeaf60705a9e", "type": "Role" }, - { "id": "dbaae8cf-10b5-4b86-a4a1-f871c94c6695", "type": "Role" }, - { "id": "bf7b1a76-6e77-406b-b258-bf5c7720e98f", "type": "Role" }, - { "id": "01c0a623-fc9b-48e9-b794-0756f8e8f067", "type": "Role" }, - { "id": "50483e42-d915-4231-9639-7fdb7fd190e5", "type": "Role" }, - { "id": "dbb9058a-0e50-45d7-ae91-66909b5d4664", "type": "Role" }, - { "id": "a82116e5-55eb-4c41-a434-62fe8a61c773", "type": "Role" }, - { "id": "f3a65bd4-b703-46df-8f7e-0174fea562aa", "type": "Role" }, - { "id": "59a6b24b-4225-4393-8165-ebaec5f55d7a", "type": "Role" }, - { "id": "0121dc95-1b9f-4aed-8bac-58c5ac466691", "type": "Role" }, - { "id": "3b55498e-47ec-484f-8136-9013221c06a9", "type": "Role" }, - { "id": "35930dcf-aceb-4bd1-b99a-8ffed403c974", "type": "Role" }, - { "id": "25f85f3c-f66c-4205-8cd5-de92dd7f0cec", "type": "Role" }, - { "id": "29c18626-4985-4dcd-85c0-193eef327366", "type": "Role" }, - { "id": "4437522e-9a86-4a41-a7da-e380edd4a97d", "type": "Role" }, - { "id": "34bf0e97-1971-4929-b999-9e2442d941d7", "type": "Role" }, - { "id": "45cc0394-e837-488b-a098-1918f48d186c", "type": "Role" }, - { "id": "be74164b-cff1-491c-8741-e671cb536e13", "type": "Role" }, - { "id": "2a60023f-3219-47ad-baa4-40e17cd02a1d", "type": "Role" }, - { "id": "338163d7-f101-4c92-94ba-ca46fe52447c", "type": "Role" }, - { "id": "cac88765-0581-4025-9725-5ebc13f729ee", "type": "Role" }, - { "id": "75359482-378d-4052-8f01-80520e7db3cd", "type": "Role" }, - { "id": "19dbc75e-c2e2-444c-a770-ec69d8559fc7", "type": "Role" }, - { "id": "b27a61ec-b99c-4d6a-b126-c4375d08ae30", "type": "Scope" }, - { "id": "84bccea3-f856-4a8a-967b-dbe0a3d53a64", "type": "Scope" }, - { "id": "280b3b69-0437-44b1-bc20-3b2fca1ee3e9", "type": "Scope" }, - { "id": "885f682f-a990-4bad-a642-36736a74b0c7", "type": "Scope" }, - { "id": "913b9306-0ce1-42b8-9137-6a7df690a760", "type": "Role" }, - { "id": "cb8f45a0-5c2e-4ea1-b803-84b870a7d7ec", "type": "Scope" }, - { "id": "4c06a06a-098a-4063-868e-5dfee3827264", "type": "Scope" }, - { "id": "1bfefb4e-e0b5-418b-a88f-73c46d2cc8e9", "type": "Role" }, - { "id": "e67e6727-c080-415e-b521-e3f35d5248e9", "type": "Scope" } - ] - }, - { - "resourceAppId": "00000002-0000-0000-c000-000000000000", - "resourceAccess": [ - { "id": "5778995a-e1bf-45b8-affa-663a9f3f4d04", "type": "Role" }, - { "id": "a42657d6-7f20-40e3-b6f0-cee03008a62a", "type": "Scope" }, - { "id": "311a71cc-e848-46a1-bdf8-97ff7156d8e6", "type": "Scope" } - ] - }, - { - "resourceAppId": "fc780465-2017-40d4-a0c5-307022471b92", - "resourceAccess": [ - { "id": "63a677ce-818c-4409-9d12-5c6d2e2a6bfe", "type": "Scope" }, - { "id": "41269fc5-d04d-4bfd-bce7-43a51cea049a", "type": "Role" } - ] - }, - { - "resourceAppId": "00000002-0000-0ff1-ce00-000000000000", - "resourceAccess": [ - { "id": "ab4f2b77-0b06-4fc1-a9de-02113fc2ab7c", "type": "Scope" }, - { "id": "dc50a0fb-09a3-484d-be87-e023b12c6440", "type": "Role" } - ] - }, - { - "resourceAppId": "00000003-0000-0ff1-ce00-000000000000", - "resourceAccess": [ - { "id": "56680e0d-d2a3-4ae1-80d8-3c4f2100e3d0", "type": "Scope" } - ] - }, - { - "resourceAppId": "48ac35b8-9aa8-4d74-927d-1f4a14a0b239", - "resourceAccess": [ - { "id": "e60370c1-e451-437e-aa6e-d76df38e5f15", "type": "Scope" } - ] - }, - { - "resourceAppId": "c5393580-f805-4401-95e8-94b7a6ef2fc2", - "resourceAccess": [ - { "id": "594c1fb6-4f81-4475-ae41-0c394909246c", "type": "Scope" } - ] - } - ] -} +{ + "isFallbackPublicClient": true, + "signInAudience": "AzureADMultipleOrgs", + "displayName": "CIPP-SAM", + "web": { + "redirectUris": [ + "https://login.microsoftonline.com/common/oauth2/nativeclient", + "https://localhost", + "http://localhost", + "http://localhost:8400" + ] + }, + "requiredResourceAccess": [ + { + "resourceAppId": "fa3d9a0c-3fb0-42cc-9193-47c7ecd2edbd", + "resourceAccess": [ + { "id": "1cebfa2a-fb4d-419e-b5f9-839b4383e05a", "type": "Scope" } + ] + }, + { + "resourceAppId": "00000003-0000-0000-c000-000000000000", + "resourceAccess": [ + { "id": "aa07f155-3612-49b8-a147-6c590df35536", "type": "Scope" }, + { "id": "0f4595f7-64b1-4e13-81bc-11a249df07a9", "type": "Scope" }, + { "id": "73e75199-7c3e-41bb-9357-167164dbb415", "type": "Scope" }, + { "id": "7ab1d787-bae7-4d5d-8db6-37ea32df9186", "type": "Scope" }, + { "id": "d01b97e9-cbc0-49fe-810a-750afd5527a3", "type": "Scope" }, + { "id": "46ca0847-7e6b-426e-9775-ea810a948356", "type": "Scope" }, + { "id": "dc38509c-b87d-4da0-bd92-6bec988bac4a", "type": "Scope" }, + { "id": "7427e0e9-2fba-42fe-b0c0-848c9e6a8182", "type": "Scope" }, + { "id": "ad902697-1014-4ef5-81ef-2b4301988e8c", "type": "Scope" }, + { "id": "572fea84-0151-49b2-9301-11cb16974376", "type": "Scope" }, + { "id": "e4c9e354-4dc5-45b8-9e7c-e1393b0b1a20", "type": "Scope" }, + { "id": "0883f392-0a7a-443d-8c76-16a6d39c7b63", "type": "Scope" }, + { "id": "7b3f05d5-f68c-4b8d-8c59-a2ecd12f24af", "type": "Scope" }, + { "id": "0c5e8a55-87a6-4556-93ab-adc52c4d862d", "type": "Scope" }, + { "id": "44642bfe-8385-4adc-8fc6-fe3cb2c375c3", "type": "Scope" }, + { "id": "662ed50a-ac44-4eef-ad86-62eed9be2a29", "type": "Scope" }, + { "id": "8696daa5-bce5-4b2e-83f9-51b6defc4e1e", "type": "Scope" }, + { "id": "6aedf524-7e1c-45a7-bd76-ded8cab8d0fc", "type": "Scope" }, + { "id": "bac3b9c2-b516-4ef4-bd3b-c2ef73d8d804", "type": "Scope" }, + { "id": "11d4cd79-5ba5-460f-803f-e22c8ab85ccd", "type": "Scope" }, + { "id": "02e97553-ed7b-43d0-ab3c-f8bace0d040c", "type": "Scope" }, + { "id": "89fe6a52-be36-487e-b7d8-d061c450a026", "type": "Scope" }, + { "id": "a367ab51-6b49-43bf-a716-a1fb06d2a174", "type": "Scope" }, + { "id": "204e0828-b5ca-4ad8-b9f3-f32a958e7cc4", "type": "Scope" }, + { "id": "4e46008b-f24c-477d-8fff-7bb4ec7aafe0", "type": "Scope" }, + { "id": "0e263e50-5827-48a4-b97c-d940288653c7", "type": "Scope" }, + { "id": "e383f46e-2787-4529-855e-0e479a3ffac0", "type": "Scope" }, + { "id": "37f7f235-527c-4136-accd-4a02d197296e", "type": "Scope" }, + { "id": "14dad69e-099b-42c9-810b-d002981feec1", "type": "Scope" }, + { "id": "f6a3db3e-f7e8-4ed2-a414-557c8c9830be", "type": "Scope" }, + { "id": "0e755559-83fb-4b44-91d0-4cc721b9323e", "type": "Scope" }, + { "id": "a84a9652-ffd3-496e-a991-22ba5529156a", "type": "Scope" }, + { "id": "1d89d70c-dcac-4248-b214-903c457af83a", "type": "Scope" }, + { "id": "2b61aa8a-6d36-4b2f-ac7b-f29867937c53", "type": "Scope" }, + { "id": "ebf0f66e-9fb1-49e4-a278-222f76911cf4", "type": "Scope" }, + { "id": "c79f8feb-a9db-4090-85f9-90d820caa0eb", "type": "Scope" }, + { "id": "bdfbf15f-ee85-4955-8675-146e8e5296b5", "type": "Scope" }, + { "id": "f81125ac-d3b7-4573-a3b2-7099cc39df9e", "type": "Scope" }, + { "id": "cac97e40-6730-457d-ad8d-4852fddab7ad", "type": "Scope" }, + { "id": "b7887744-6746-4312-813d-72daeaee7e2d", "type": "Scope" }, + { "id": "48971fc1-70d7-4245-af77-0beb29b53ee2", "type": "Scope" }, + { "id": "aec28ec7-4d02-4e8c-b864-50163aea77eb", "type": "Scope" }, + { "id": "a9ff19c2-f369-4a95-9a25-ba9d460efc8e", "type": "Scope" }, + { "id": "59dacb05-e88d-4c13-a684-59f1afc8cc98", "type": "Scope" }, + { "id": "b98bfd41-87c6-45cc-b104-e2de4f0dafb9", "type": "Scope" }, + { "id": "2f9ee017-59c1-4f1d-9472-bd5529a7b311", "type": "Scope" }, + { "id": "951183d1-1a61-466f-a6d1-1fde911bfd95", "type": "Scope" }, + { "id": "637d7bec-b31e-4deb-acc9-24275642a2c9", "type": "Scope" }, + { "id": "101147cf-4178-4455-9d58-02b5c164e759", "type": "Scope" }, + { "id": "cc83893a-e232-4723-b5af-bd0b01bcfe65", "type": "Scope" }, + { "id": "233e0cf1-dd62-48bc-b65b-b38fe87fcf8e", "type": "Scope" }, + { "id": "d649fb7c-72b4-4eec-b2b4-b15acf79e378", "type": "Scope" }, + { "id": "485be79e-c497-4b35-9400-0e3fa7f2a5d4", "type": "Scope" }, + { "id": "9d8982ae-4365-4f57-95e9-d6032a4c0b87", "type": "Scope" }, + { "id": "48638b3c-ad68-4383-8ac4-e6880ee6ca57", "type": "Scope" }, + { "id": "39d65650-9d3e-4223-80db-a335590d027e", "type": "Scope" }, + { "id": "4a06efd2-f825-4e34-813e-82a57b03d1ee", "type": "Scope" }, + { "id": "f3bfad56-966e-4590-a536-82ecf548ac1e", "type": "Scope" }, + { "id": "4d135e65-66b8-41a8-9f8b-081452c91774", "type": "Scope" }, + { "id": "2eadaff8-0bce-4198-a6b9-2cfc35a30075", "type": "Scope" }, + { "id": "0c3e411a-ce45-4cd1-8f30-f99a3efa7b11", "type": "Scope" }, + { "id": "edb72de9-4252-4d03-a925-451deef99db7", "type": "Scope" }, + { "id": "767156cb-16ae-4d10-8f8b-41b657c8c8c8", "type": "Scope" }, + { "id": "7e823077-d88e-468f-a337-e18f1f0e6c7c", "type": "Scope" }, + { "id": "edd3c878-b384-41fd-95ad-e7407dd775be", "type": "Scope" }, + { "id": "40b534c3-9552-4550-901b-23879c90bcf9", "type": "Scope" }, + { "id": "bf3fbf03-f35f-4e93-963e-47e4d874c37a", "type": "Scope" }, + { "id": "5248dcb1-f83b-4ec3-9f4d-a4428a961a72", "type": "Scope" }, + { "id": "c395395c-ff9a-4dba-bc1f-8372ba9dca84", "type": "Scope" }, + { "id": "2e25a044-2580-450d-8859-42eeb6e996c0", "type": "Scope" }, + { "id": "0ce33576-30e8-43b7-99e5-62f8569a4002", "type": "Scope" }, + { "id": "207e0cb1-3ce7-4922-b991-5a760c346ebc", "type": "Scope" }, + { "id": "093f8818-d05f-49b8-95bc-9d2a73e9a43c", "type": "Scope" }, + { "id": "7825d5d6-6049-4ce7-bdf6-3b8d53f4bcd0", "type": "Scope" }, + { "id": "2104a4db-3a2f-4ea0-9dba-143d457dc666", "type": "Scope" }, + { "id": "eda39fa6-f8cf-4c3c-a909-432c683e4c9b", "type": "Scope" }, + { "id": "55896846-df78-47a7-aa94-8d3d4442ca7f", "type": "Scope" }, + { "id": "aa85bf13-d771-4d5d-a9e6-bca04ce44edf", "type": "Scope" }, + { "id": "ee928332-e9c2-4747-b4a0-f8c164b68de6", "type": "Scope" }, + { "id": "c975dd04-a06e-4fbb-9704-62daad77bb49", "type": "Scope" }, + { "id": "c37c9b61-7762-4bff-a156-afc0005847a0", "type": "Scope" }, + { "id": "b9abcc4f-94fc-4457-9141-d20ce80ec952", "type": "Scope" }, + { "id": "128ca929-1a19-45e6-a3b8-435ec44a36ba", "type": "Scope" }, + { "id": "b27add92-efb2-4f16-84f5-8108ba77985c", "type": "Scope" }, + { "id": "3404d2bf-2b13-457e-a330-c24615765193", "type": "Scope" }, + { "id": "b955410e-7715-4a88-a940-dfd551018df3", "type": "Scope" }, + { "id": "9e4862a5-b68f-479e-848a-4e07e25c9916", "type": "Scope" }, + { "id": "e0a7cdbb-08b0-4697-8264-0069786e9674", "type": "Scope" }, + { "id": "bb6f654c-d7fd-4ae3-85c3-fc380934f515", "type": "Scope" }, + { "id": "5b07b0dd-2377-4e44-a38d-703f09a0dc3c", "type": "Role" }, + { "id": "19b94e34-907c-4f43-bde9-38b1909ed408", "type": "Role" }, + { "id": "999f8c63-0a38-4f1b-91fd-ed1947bdd1a9", "type": "Role" }, + { "id": "292d869f-3427-49a8-9dab-8c70152b74e9", "type": "Role" }, + { "id": "2f51be20-0bb4-4fed-bf7b-db946066c75e", "type": "Role" }, + { "id": "58ca0d9a-1575-47e1-a3cb-007ef2e4583b", "type": "Role" }, + { "id": "06a5fe6d-c49d-46a7-b082-56b1b14103c7", "type": "Role" }, + { "id": "246dd0d5-5bd0-4def-940b-0421030a5b68", "type": "Role" }, + { "id": "bf394140-e372-4bf9-a898-299cfc7564e5", "type": "Role" }, + { "id": "741f803b-c850-494e-b5df-cde7c675a1ca", "type": "Role" }, + { "id": "230c1aed-a721-4c5d-9cb4-a90514e508ef", "type": "Role" }, + { "id": "b633e1c5-b582-4048-a93e-9f11b44c7e96", "type": "Role" }, + { "id": "5b567255-7703-4780-807c-7be8301ae99b", "type": "Role" }, + { "id": "62a82d76-70ea-41e2-9197-370581804d09", "type": "Role" }, + { "id": "7ab1d382-f21e-4acd-a863-ba3e13f7da61", "type": "Role" }, + { "id": "1138cb37-bd11-4084-a2b7-9f71582aeddb", "type": "Role" }, + { "id": "78145de6-330d-4800-a6ce-494ff2d33d07", "type": "Role" }, + { "id": "9241abd9-d0e6-425a-bd4f-47ba86e767a4", "type": "Role" }, + { "id": "5b07b0dd-2377-4e44-a38d-703f09a0dc3c", "type": "Role" }, + { "id": "243333ab-4d21-40cb-a475-36241daa0842", "type": "Role" }, + { "id": "e330c4f0-4170-414e-a55a-2f022ec2b57b", "type": "Role" }, + { "id": "5ac13192-7ace-4fcf-b828-1a26f28068ee", "type": "Role" }, + { "id": "2f6817f8-7b12-4f0f-bc18-eeaf60705a9e", "type": "Role" }, + { "id": "dbaae8cf-10b5-4b86-a4a1-f871c94c6695", "type": "Role" }, + { "id": "bf7b1a76-6e77-406b-b258-bf5c7720e98f", "type": "Role" }, + { "id": "01c0a623-fc9b-48e9-b794-0756f8e8f067", "type": "Role" }, + { "id": "50483e42-d915-4231-9639-7fdb7fd190e5", "type": "Role" }, + { "id": "dbb9058a-0e50-45d7-ae91-66909b5d4664", "type": "Role" }, + { "id": "a82116e5-55eb-4c41-a434-62fe8a61c773", "type": "Role" }, + { "id": "f3a65bd4-b703-46df-8f7e-0174fea562aa", "type": "Role" }, + { "id": "59a6b24b-4225-4393-8165-ebaec5f55d7a", "type": "Role" }, + { "id": "0121dc95-1b9f-4aed-8bac-58c5ac466691", "type": "Role" }, + { "id": "3b55498e-47ec-484f-8136-9013221c06a9", "type": "Role" }, + { "id": "35930dcf-aceb-4bd1-b99a-8ffed403c974", "type": "Role" }, + { "id": "25f85f3c-f66c-4205-8cd5-de92dd7f0cec", "type": "Role" }, + { "id": "29c18626-4985-4dcd-85c0-193eef327366", "type": "Role" }, + { "id": "4437522e-9a86-4a41-a7da-e380edd4a97d", "type": "Role" }, + { "id": "34bf0e97-1971-4929-b999-9e2442d941d7", "type": "Role" }, + { "id": "45cc0394-e837-488b-a098-1918f48d186c", "type": "Role" }, + { "id": "be74164b-cff1-491c-8741-e671cb536e13", "type": "Role" }, + { "id": "2a60023f-3219-47ad-baa4-40e17cd02a1d", "type": "Role" }, + { "id": "338163d7-f101-4c92-94ba-ca46fe52447c", "type": "Role" }, + { "id": "cac88765-0581-4025-9725-5ebc13f729ee", "type": "Role" }, + { "id": "75359482-378d-4052-8f01-80520e7db3cd", "type": "Role" }, + { "id": "19dbc75e-c2e2-444c-a770-ec69d8559fc7", "type": "Role" }, + { "id": "b27a61ec-b99c-4d6a-b126-c4375d08ae30", "type": "Scope" }, + { "id": "84bccea3-f856-4a8a-967b-dbe0a3d53a64", "type": "Scope" }, + { "id": "280b3b69-0437-44b1-bc20-3b2fca1ee3e9", "type": "Scope" }, + { "id": "885f682f-a990-4bad-a642-36736a74b0c7", "type": "Scope" }, + { "id": "913b9306-0ce1-42b8-9137-6a7df690a760", "type": "Role" }, + { "id": "cb8f45a0-5c2e-4ea1-b803-84b870a7d7ec", "type": "Scope" }, + { "id": "4c06a06a-098a-4063-868e-5dfee3827264", "type": "Scope" }, + { "id": "1bfefb4e-e0b5-418b-a88f-73c46d2cc8e9", "type": "Role" }, + { "id": "e67e6727-c080-415e-b521-e3f35d5248e9", "type": "Scope" }, + { "id": "b6890674-9dd5-4e42-bb15-5af07f541ae1", "type": "Role" } + ] + }, + { + "resourceAppId": "00000002-0000-0000-c000-000000000000", + "resourceAccess": [ + { "id": "5778995a-e1bf-45b8-affa-663a9f3f4d04", "type": "Role" }, + { "id": "a42657d6-7f20-40e3-b6f0-cee03008a62a", "type": "Scope" }, + { "id": "311a71cc-e848-46a1-bdf8-97ff7156d8e6", "type": "Scope" } + ] + }, + { + "resourceAppId": "fc780465-2017-40d4-a0c5-307022471b92", + "resourceAccess": [ + { "id": "63a677ce-818c-4409-9d12-5c6d2e2a6bfe", "type": "Scope" }, + { "id": "41269fc5-d04d-4bfd-bce7-43a51cea049a", "type": "Role" } + ] + }, + { + "resourceAppId": "00000002-0000-0ff1-ce00-000000000000", + "resourceAccess": [ + { "id": "ab4f2b77-0b06-4fc1-a9de-02113fc2ab7c", "type": "Scope" }, + { "id": "dc50a0fb-09a3-484d-be87-e023b12c6440", "type": "Role" } + ] + }, + { + "resourceAppId": "00000003-0000-0ff1-ce00-000000000000", + "resourceAccess": [ + { "id": "56680e0d-d2a3-4ae1-80d8-3c4f2100e3d0", "type": "Scope" } + ] + }, + { + "resourceAppId": "48ac35b8-9aa8-4d74-927d-1f4a14a0b239", + "resourceAccess": [ + { "id": "e60370c1-e451-437e-aa6e-d76df38e5f15", "type": "Scope" } + ] + }, + { + "resourceAppId": "c5393580-f805-4401-95e8-94b7a6ef2fc2", + "resourceAccess": [ + { "id": "594c1fb6-4f81-4475-ae41-0c394909246c", "type": "Scope" } + ] + } + ] +} diff --git a/Modules/CIPPCore/Public/Send-CIPPAlert.ps1 b/Modules/CIPPCore/Public/Send-CIPPAlert.ps1 index 8fc9e31f7bdf..89bd2ade79d2 100644 --- a/Modules/CIPPCore/Public/Send-CIPPAlert.ps1 +++ b/Modules/CIPPCore/Public/Send-CIPPAlert.ps1 @@ -79,7 +79,7 @@ function Send-CIPPAlert { } catch { Write-Information "Could not send alerts to webhook: $($_.Exception.message)" - Write-LogMessage -API 'Webhook Alerts' -message "Could not send alerts to webhook: $($_.Exception.message)" -tenant $TenantFilter -sev info + Write-LogMessage -API 'Webhook Alerts' -message "Could not send alerts to webhook: $($_.Exception.message)" -tenant $TenantFilter -sev error -LogData (Get-CippException -Exception $_) } } Write-Information 'Trying to send to PSA' diff --git a/Modules/CIPPCore/Public/Set-CIPPForwarding.ps1 b/Modules/CIPPCore/Public/Set-CIPPForwarding.ps1 index 593344a886ef..130ff65ff430 100644 --- a/Modules/CIPPCore/Public/Set-CIPPForwarding.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPForwarding.ps1 @@ -1,15 +1,50 @@ function Set-CIPPForwarding { + <# + .SYNOPSIS + Set forwarding for a user mailbox. + + .DESCRIPTION + Set forwarding for a user mailbox. + + .PARAMETER userid + User ID to set forwarding for. + + .PARAMETER forwardingSMTPAddress + SMTP address to forward to. + + .PARAMETER tenantFilter + Tenant to manage for forwarding. + + .PARAMETER username + Username to manage for forwarding. + + .PARAMETER ExecutingUser + CIPP user executing the command. + + .PARAMETER APIName + Name of the API executing the command. + + .PARAMETER Forward + Forwarding address. + + .PARAMETER KeepCopy + Keep a copy of the email. + + .PARAMETER Disable + Disable forwarding. + + #> [CmdletBinding(SupportsShouldProcess = $true)] param( - $userid, - $forwardingSMTPAddress, - $tenantFilter, - $username, - $ExecutingUser, - $APIName = 'Forwarding', - $Forward, - $KeepCopy, - $Disable + [string]$userid, + [string]$forwardingSMTPAddress, + [string]$tenantFilter, + [string]$username, + [string]$ExecutingUser, + [string]$APIName = 'Forwarding', + [string]$Forward, + [bool]$KeepCopy, + [bool]$Disable ) try { diff --git a/Modules/CIPPCore/Public/Set-CIPPPerUserMFA.ps1 b/Modules/CIPPCore/Public/Set-CIPPPerUserMFA.ps1 index 1c92a5e9c5d2..f7f88a53fe11 100644 --- a/Modules/CIPPCore/Public/Set-CIPPPerUserMFA.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPPerUserMFA.ps1 @@ -48,8 +48,8 @@ function Set-CIPPPerUserMFA { } } - $Requests = New-GraphBulkRequest -tenantid $tenantfilter -scope 'https://graph.microsoft.com/.default' -Requests @($Requests) -asapp $true + "Successfully set Per user MFA State for $userId" $Users = foreach ($id in $userId) { diff --git a/Modules/CIPPCore/Public/Set-CIPPSharePointOwner.ps1 b/Modules/CIPPCore/Public/Set-CIPPSharePointPerms.ps1 similarity index 87% rename from Modules/CIPPCore/Public/Set-CIPPSharePointOwner.ps1 rename to Modules/CIPPCore/Public/Set-CIPPSharePointPerms.ps1 index 3acdfc3d314f..ab447f685994 100644 --- a/Modules/CIPPCore/Public/Set-CIPPSharePointOwner.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPSharePointPerms.ps1 @@ -1,4 +1,4 @@ -function Set-CIPPSharePointOwner { +function Set-CIPPSharePointPerms { [CmdletBinding()] param ( $userid, @@ -19,8 +19,8 @@ function Set-CIPPSharePointOwner { if (!$URL) { $URL = (New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/users/$($UserId)/Drives" -asapp $true -tenantid $TenantFilter).WebUrl } - $OnMicrosoft = (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/domains?$top=999' -tenantid $TenantFilter | Where-Object -Property isInitial -EQ $true).id.split('.') | Select-Object -First 1 - $AdminUrl = "https://$($OnMicrosoft)-admin.sharepoint.com" + $tenantName = (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/sites/root' -tenantid $TenantFilter).id.Split('.')[0] + $AdminUrl = "https://$($tenantName)-admin.sharepoint.com" $XML = @" diff --git a/Modules/CIPPCore/Public/Set-CIPPSignInState.ps1 b/Modules/CIPPCore/Public/Set-CIPPSignInState.ps1 index ea26d3d309ed..4c99b82c84df 100644 --- a/Modules/CIPPCore/Public/Set-CIPPSignInState.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPSignInState.ps1 @@ -1,7 +1,7 @@ function Set-CIPPSignInState { [CmdletBinding()] param ( - $userid, + $UserId, [bool]$AccountEnabled, $TenantFilter, $APIName = 'Disable User Sign-in', @@ -11,13 +11,14 @@ function Set-CIPPSignInState { try { $body = @{ accountEnabled = [bool]$AccountEnabled - } | ConvertTo-Json -Compress -Depth 1 - $SignInState = New-GraphPostRequest -uri "https://graph.microsoft.com/v1.0/users/$($userid)" -tenantid $TenantFilter -type PATCH -body $body -verbose - Write-LogMessage -user $ExecutingUser -API $APIName -message "Set account enabled state to $AccountEnabled for $userid" -Sev 'Info' -tenant $TenantFilter - return "Set account enabled state to $AccountEnabled for $userid" + } + $body = ConvertTo-Json -InputObject $body -Compress -Depth 5 + $null = New-GraphPostRequest -uri "https://graph.microsoft.com/v1.0/users/$($UserId)" -tenantid $TenantFilter -type PATCH -body $body -verbose + Write-LogMessage -user $ExecutingUser -API $APIName -message "Set account enabled state to $AccountEnabled for $UserId" -Sev 'Info' -tenant $TenantFilter + return "Set account enabled state to $AccountEnabled for $UserId" } catch { - Write-LogMessage -user $ExecutingUser -API $APIName -message "Could not disable sign in for $userid. Error: $($_.Exception.Message)" -Sev 'Error' -tenant $TenantFilter - return "Could not disable $userid. Error: $($_.Exception.Message)" + Write-LogMessage -user $ExecutingUser -API $APIName -message "Could not disable sign in for $UserId. Error: $($_.Exception.Message)" -Sev 'Error' -tenant $TenantFilter + return "Could not disable $UserId. Error: $($_.Exception.Message)" } } diff --git a/Modules/CIPPCore/Public/Set-CIPPUserJITAdmin.ps1 b/Modules/CIPPCore/Public/Set-CIPPUserJITAdmin.ps1 index 692b6c4828ef..e25bf6443acd 100644 --- a/Modules/CIPPCore/Public/Set-CIPPUserJITAdmin.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPUserJITAdmin.ps1 @@ -91,6 +91,17 @@ function Set-CIPPUserJITAdmin { $null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/directoryRoles(roleTemplateId='$($_)')/members/`$ref" -tenantid $TenantFilter -body $Json -ErrorAction SilentlyContinue } catch {} } + $UserEnabled = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($UserObj.id)?`$select=accountEnabled" -tenantid $TenantFilter).accountEnabled + if (-not $UserEnabled) { + $Body = @{ + accountEnabled = $true + } + $Json = ConvertTo-Json -Depth 5 -InputObject $Body + try { + New-GraphPOSTRequest -type PATCH -uri "https://graph.microsoft.com/beta/users/$($UserObj.id)" -tenantid $TenantFilter -body $Json | Out-Null + } catch {} + } + Set-CIPPUserJITAdminProperties -TenantFilter $TenantFilter -UserId $UserObj.id -Enabled -Expiration $Expiration | Out-Null return "Added admin roles to user $($UserObj.displayName) ($($UserObj.userPrincipalName))" } @@ -115,10 +126,13 @@ function Set-CIPPUserJITAdmin { $Body = @{ accountEnabled = $false } - $Json = ConvertTo-Json -Depth 5 -InputObject $Body + $Json = ConvertTo-Json -Depth 5 -InputObject $Body -Compress try { - New-GraphPOSTRequest -type PATCH -uri "https://graph.microsoft.com/beta/users/$($UserObj.id)" -tenantid $TenantFilter -body $Json - Set-CIPPUserJITAdminProperties -TenantFilter $TenantFilter -UserId $UserObj.id -Enabled:$false | Out-Null + Write-Information "Disabling user $($UserObj.displayName) ($($User.UserPrincipalName))" + Write-Information $Json + Write-Information "https://graph.microsoft.com/beta/users/$($User.UserPrincipalName)" + $null = New-GraphPOSTRequest -type PATCH -uri "https://graph.microsoft.com/beta/users/$($User.UserPrincipalName)" -tenantid $TenantFilter -body $Json + Set-CIPPUserJITAdminProperties -TenantFilter $TenantFilter -UserId $User.UserPrincipalName -Clear | Out-Null return "Disabled user $($UserObj.displayName) ($($UserObj.userPrincipalName))" } catch { return "Error disabling user $($UserObj.displayName) ($($UserObj.userPrincipalName)): $($_.Exception.Message)" diff --git a/Modules/CIPPCore/Public/Standards/Get-CIPPStandards.ps1 b/Modules/CIPPCore/Public/Standards/Get-CIPPStandards.ps1 index 6e941c7608cd..58626e946e74 100644 --- a/Modules/CIPPCore/Public/Standards/Get-CIPPStandards.ps1 +++ b/Modules/CIPPCore/Public/Standards/Get-CIPPStandards.ps1 @@ -64,7 +64,7 @@ function Get-CIPPStandards { } else { foreach ($Setting in $CurrentStandard.PSObject.Properties.Name) { # Write-Host "$Setting - Current: $($CurrentStandard.$Setting) | Computed: $($ComputedStandards[$StandardName].$($Setting))" - if ($CurrentStandard.$Setting -ne $false -and $CurrentStandard.$Setting -ne $ComputedStandards[$StandardName].$($Setting) -and ![string]::IsNullOrEmpty($CurrentStandard.$Setting)) { + if ($CurrentStandard.$Setting -ne $false -and $CurrentStandard.$Setting -ne $ComputedStandards[$StandardName].$($Setting) -and ![string]::IsNullOrWhiteSpace($CurrentStandard.$Setting)) { #Write-Host "Overriding $Setting for $StandardName at tenant level" if ($ComputedStandards[$StandardName].PSObject.Properties.Name -contains $Setting) { $ComputedStandards[$StandardName].$($Setting) = $CurrentStandard.$Setting @@ -86,4 +86,4 @@ function Get-CIPPStandards { } } } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPConfig.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPConfig.ps1 index b6ffea3946d5..4f168c0e6d2b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPConfig.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPConfig.ps1 @@ -7,15 +7,31 @@ function Invoke-CIPPStandardAPConfig { If ($Settings.remediate -eq $true) { - $APINAME = 'Standards' try { Write-Host $($settings | ConvertTo-Json -Depth 100) if ($settings.NotLocalAdmin -eq $true) { $usertype = 'Standard' } else { $usertype = 'Administrator' } $DeploymentMode = if ($settings.DeploymentMode -eq 'true') { 'shared' } else { 'singleUser' } - Set-CIPPDefaultAPDeploymentProfile -tenantFilter $tenant -displayname $settings.DisplayName -description $settings.Description -usertype $usertype -DeploymentMode $DeploymentMode -assignto $settings.Assignto -devicenameTemplate $Settings.DeviceNameTemplate -allowWhiteGlove $Settings.allowWhiteGlove -CollectHash $Settings.CollectHash -hideChangeAccount $Settings.HideChangeAccount -hidePrivacy $Settings.HidePrivacy -hideTerms $Settings.HideTerms -Autokeyboard $Settings.Autokeyboard -Language $Settings.languages.value + + $Parameters = @{ + tenantFilter = $tenant + displayname = $settings.DisplayName + description = $settings.Description + usertype = $usertype + DeploymentMode = $DeploymentMode + assignto = $settings.Assignto + devicenameTemplate = $Settings.DeviceNameTemplate + allowWhiteGlove = $Settings.allowWhiteGlove + CollectHash = $Settings.CollectHash + hideChangeAccount = $Settings.HideChangeAccount + hidePrivacy = $Settings.HidePrivacy + hideTerms = $Settings.HideTerms + Autokeyboard = $Settings.Autokeyboard + Language = $Settings.languages.value + } + Set-CIPPDefaultAPDeploymentProfile @Parameters } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - #Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create Default Autopilot config: $ErrorMessage" -sev 'Error' + # Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create Default Autopilot config: $ErrorMessage" -sev 'Error' throw $ErrorMessage } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPESP.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPESP.ps1 index 2749ec946573..478541ac8140 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPESP.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPESP.ps1 @@ -5,9 +5,20 @@ function Invoke-CIPPStandardAPESP { #> param($Tenant, $Settings) If ($Settings.remediate -eq $true) { - $APINAME = 'Standards' try { - Set-CIPPDefaultAPEnrollment -TenantFilter $Tenant -ShowProgress $Settings.ShowProgress -BlockDevice $Settings.blockDevice -AllowReset $Settings.AllowReset -EnableLog $Settings.EnableLog -ErrorMessage $Settings.ErrorMessage -TimeOutInMinutes $Settings.TimeOutInMinutes -AllowFail $Settings.AllowFail -OBEEOnly $Settings.OBEEOnly + $Parameters = @{ + TenantFilter = $Tenant + ShowProgress = $Settings.ShowProgress + BlockDevice = $Settings.blockDevice + AllowReset = $Settings.AllowReset + EnableLog = $Settings.EnableLog + ErrorMessage = $Settings.ErrorMessage + TimeOutInMinutes = $Settings.TimeOutInMinutes + AllowFail = $Settings.AllowFail + OBEEOnly = $Settings.OBEEOnly + } + + Set-CIPPDefaultAPEnrollment @Parameters } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message throw $ErrorMessage @@ -15,4 +26,4 @@ function Invoke-CIPPStandardAPESP { } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 index 29d1862ecb01..ebf92d21e199 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 @@ -4,15 +4,16 @@ function Invoke-CIPPStandardActivityBasedTimeout { Internal #> param($Tenant, $Settings) - - if ($Settings.timeout -eq 'Select a value') { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'No value selected for Activity Based Timeout' -sev Error - Exit + + # Input validation + if ([string]::IsNullOrWhiteSpace($Settings.timeout) -or $Settings.timeout -eq 'Select a value' ) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'ActivityBasedTimeout: Invalid timeout parameter set' -sev Error + Return } - + # Backwards compatibility for v5.7.0 and older if ($null -eq $Settings.timeout ) { $Settings.timeout = '01:00:00' } - + $State = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/activityBasedTimeoutPolicies' -tenantid $tenant $StateIsCorrect = $State.definition -like "*$($Settings.timeout)*" @@ -29,11 +30,11 @@ function Invoke-CIPPStandardActivityBasedTimeout { $body = ConvertTo-Json -InputObject $PolicyTemplate -Depth 10 -Compress # Switch between parameter sets if the policy already exists - if ($null -eq $State.id) { - $RequestType = 'POST' + if ($null -eq $State.id) { + $RequestType = 'POST' $URI = 'https://graph.microsoft.com/beta/policies/activityBasedTimeoutPolicies' - } else { - $RequestType = 'PATCH' + } else { + $RequestType = 'PATCH' $URI = "https://graph.microsoft.com/beta/policies/activityBasedTimeoutPolicies/$($State.id)" } New-GraphPostRequest -tenantid $tenant -Uri $URI -Type $RequestType -Body $body -ContentType 'application/json' diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 index 1eeb304a0768..17eed3cd2d53 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 @@ -34,7 +34,7 @@ function Invoke-CIPPStandardAntiPhishPolicy { $RuleState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AntiPhishRule' | Where-Object -Property Name -EQ "CIPP $PolicyName" | Select-Object Name, AntiPhishPolicy, Priority, RecipientDomainIs - + $RuleStateIsCorrect = ($RuleState.Name -eq "CIPP $PolicyName") -and ($RuleState.AntiPhishPolicy -eq $PolicyName) -and ($RuleState.Priority -eq 0) -and @@ -81,9 +81,9 @@ function Invoke-CIPPStandardAntiPhishPolicy { if ($RuleStateIsCorrect -eq $false) { $cmdparams = @{ - AntiPhishPolicy = $PolicyName - Priority = 0 - RecipientDomainIs = $AcceptedDomains.Name + AntiPhishPolicy = $PolicyName + Priority = 0 + RecipientDomainIs = $AcceptedDomains.Name } try { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 index e969b5ae062d..1312fdb6089a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 @@ -47,4 +47,4 @@ function Invoke-CIPPStandardAtpPolicyForO365 { Add-CIPPBPAField -FieldName 'AtpPolicyForO365' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 index fb68e60d11c7..acb6bf9834a1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 @@ -42,7 +42,7 @@ function Invoke-CIPPStandardAuditLog { Write-LogMessage -API 'Standards' -tenant $tenant -message 'Unified Audit Log is not enabled' -sev Alert } } - + if ($Settings.report -eq $true) { Add-CIPPBPAField -FieldName 'AuditLog' -FieldValue $AuditLogEnabled -StoreAs bool -Tenant $tenant diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoExpandArchive.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoExpandArchive.ps1 index 1763b0f83171..53d29e442822 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoExpandArchive.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoExpandArchive.ps1 @@ -8,7 +8,7 @@ function Invoke-CIPPStandardAutoExpandArchive { If ($Settings.remediate -eq $true) { Write-Host 'Time to remediate' - + if ($CurrentState) { Write-LogMessage -API 'Standards' -tenant $tenant -message 'Auto Expanding Archive is already enabled.' -sev Info } else { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 index 24d4a7c0ee3b..406f0c06bd84 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 @@ -5,16 +5,21 @@ function Invoke-CIPPStandardBookings { #> param($Tenant, $Settings) - # Input validation - if ([string]::isNullOrEmpty($Settings.state) -or $Settings.state -eq 'Select a value') { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'BookingsEnabled: Invalid state parameter set' -sev Error - Exit - } - $CurrentState = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig').BookingsEnabled $WantedState = if ($Settings.state -eq 'true') { $true } else { $false } $StateIsCorrect = if ($CurrentState -eq $WantedState) { $true } else { $false } + if ($Settings.report -eq $true) { + # Default is not set, not set means it's enabled + if ($null -eq $CurrentState ) { $CurrentState = $true } + Add-CIPPBPAField -FieldName 'BookingsState' -FieldValue $CurrentState -StoreAs bool -Tenant $tenant + } + + # Input validation + if (([string]::IsNullOrWhiteSpace($Settings.state) -or $Settings.state -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'BookingsEnabled: Invalid state parameter set' -sev Error + Return + } if ($Settings.remediate -eq $true) { Write-Host 'Time to remediate' if ($StateIsCorrect -eq $false) { @@ -39,10 +44,6 @@ function Invoke-CIPPStandardBookings { } } - if ($Settings.report -eq $true) { - # Default is not set, not set means it's enabled - if ($null -eq $CurrentState ) { $CurrentState = $true } - Add-CIPPBPAField -FieldName 'BookingsState' -FieldValue $CurrentState -StoreAs bool -Tenant $tenant - } -} \ No newline at end of file + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBranding.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBranding.ps1 index 0fa6ed4b3813..2f3841588d28 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBranding.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBranding.ps1 @@ -14,7 +14,7 @@ function Invoke-CIPPStandardBranding { Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Could not get the branding for $Tenant. This tenant might not have premium licenses available: $ErrorMessage" -Sev Error } - $StateIsCorrect = ($CurrentState.signInPageText -eq $Settings.signInPageText) -and + $StateIsCorrect = ($CurrentState.signInPageText -eq $Settings.signInPageText) -and ($CurrentState.usernameHintText -eq $Settings.usernameHintText) -and ($CurrentState.loginPageTextVisibilitySettings.hideAccountResetCredentials -eq $Settings.hideAccountResetCredentials) -and ($CurrentState.loginPageLayoutConfiguration.layoutTemplateType -eq $Settings.layoutTemplateType) -and @@ -23,30 +23,30 @@ function Invoke-CIPPStandardBranding { If ($Settings.remediate -eq $true) { if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Branding is already applied correctly." -Sev Info + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Branding is already applied correctly.' -Sev Info } else { try { $GraphRequest = @{ - tenantID = $Tenant - uri = "https://graph.microsoft.com/beta/organization/$($TenantId.customerId)/branding/localizations/0" - AsApp = $true - Type = 'PATCH' + tenantID = $Tenant + uri = "https://graph.microsoft.com/beta/organization/$($TenantId.customerId)/branding/localizations/0" + AsApp = $true + Type = 'PATCH' ContentType = 'application/json; charset=utf-8' - Body = [pscustomobject]@{ - signInPageText = $Settings.signInPageText - usernameHintText = $Settings.usernameHintText + Body = [pscustomobject]@{ + signInPageText = $Settings.signInPageText + usernameHintText = $Settings.usernameHintText loginPageTextVisibilitySettings = [pscustomobject]@{ hideAccountResetCredentials = $Settings.hideAccountResetCredentials } - loginPageLayoutConfiguration = [pscustomobject]@{ + loginPageLayoutConfiguration = [pscustomobject]@{ layoutTemplateType = $Settings.layoutTemplateType - isHeaderShown = $Settings.isHeaderShown - isFooterShown = $Settings.isFooterShown + isHeaderShown = $Settings.isHeaderShown + isFooterShown = $Settings.isFooterShown } } | ConvertTo-Json -Compress } New-GraphPostRequest @GraphRequest - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Successfully updated branding." -Sev Info + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully updated branding.' -Sev Info } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to update branding. Error: $($ErrorMessage)" -Sev Error diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 index 4994b6cf91c1..19c6926d5af4 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 @@ -5,16 +5,22 @@ function Invoke-CIPPStandardCloudMessageRecall { #> param($Tenant, $Settings) - # Input validation - if ([string]::isNullOrEmpty($Settings.state) -or $Settings.state -eq 'Select a value') { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'MessageRecallEnabled: Invalid state parameter set' -sev Error - Exit - } - $CurrentState = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig').MessageRecallEnabled $WantedState = if ($Settings.state -eq 'true') { $true } else { $false } $StateIsCorrect = if ($CurrentState -eq $WantedState) { $true } else { $false } + if ($Settings.report -eq $true) { + # Default is not set, not set means it's enabled + if ($null -eq $CurrentState ) { $CurrentState = $true } + Add-CIPPBPAField -FieldName 'MessageRecall' -FieldValue $CurrentState -StoreAs bool -Tenant $tenant + } + + # Input validation + if (([string]::IsNullOrWhiteSpace($Settings.state) -or $Settings.state -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'MessageRecallEnabled: Invalid state parameter set' -sev Error + Return + } + if ($Settings.remediate -eq $true) { Write-Host 'Time to remediate' if ($StateIsCorrect -eq $false) { @@ -39,10 +45,6 @@ function Invoke-CIPPStandardCloudMessageRecall { } } - if ($Settings.report -eq $true) { - # Default is not set, not set means it's enabled - if ($null -eq $CurrentState ) { $CurrentState = $true } - Add-CIPPBPAField -FieldName 'MessageRecall' -FieldValue $CurrentState -StoreAs bool -Tenant $tenant - } -} \ No newline at end of file + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccess.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccess.ps1 index 4e7a3b0b34e0..c3c047f35421 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccess.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccess.ps1 @@ -1,26 +1,26 @@ function Invoke-CIPPStandardConditionalAccess { - <# + <# .FUNCTIONALITY Internal #> - param($Tenant, $Settings) - If ($Settings.remediate -eq $true) { + param($Tenant, $Settings) + If ($Settings.remediate -eq $true) { - $APINAME = 'Standards' + $APINAME = 'Standards' - foreach ($Template in $Settings.TemplateList) { - try { - $Table = Get-CippTable -tablename 'templates' - $Filter = "PartitionKey eq 'CATemplate' and RowKey eq '$($Template.value)'" - $JSONObj = (Get-AzDataTableEntity @Table -Filter $Filter).JSON - $CAPolicy = New-CIPPCAPolicy -TenantFilter $tenant -state $request.body.NewState -RawJSON $JSONObj -Overwrite $true -APIName $APIName -ExecutingUser $request.headers.'x-ms-client-principal' -ReplacePattern 'displayName' - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create or update conditional access rule $($JSONObj.displayName). Error: $ErrorMessage" -sev 'Error' - } - } + foreach ($Template in $Settings.TemplateList) { + try { + $Table = Get-CippTable -tablename 'templates' + $Filter = "PartitionKey eq 'CATemplate' and RowKey eq '$($Template.value)'" + $JSONObj = (Get-AzDataTableEntity @Table -Filter $Filter).JSON + $null = New-CIPPCAPolicy -TenantFilter $tenant -state $request.body.NewState -RawJSON $JSONObj -Overwrite $true -APIName $APIName -ExecutingUser $request.headers.'x-ms-client-principal' -ReplacePattern 'displayName' + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create or update conditional access rule $($JSONObj.displayName). Error: $ErrorMessage" -sev 'Error' + } + } - } + } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 index b8ee94aafe9b..81cbdc6e5167 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 @@ -4,7 +4,7 @@ function Invoke-CIPPStandardDelegateSentItems { Internal #> param($Tenant, $Settings) - $Mailboxes = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-Mailbox' -cmdParams @{ RecipientTypeDetails = @('UserMailbox', 'SharedMailbox') } | + $Mailboxes = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-Mailbox' -cmdParams @{ RecipientTypeDetails = @('UserMailbox', 'SharedMailbox') } | Where-Object { $_.MessageCopyForSendOnBehalfEnabled -eq $false -or $_.MessageCopyForSentAsEnabled -eq $false } Write-Host "Mailboxes: $($Mailboxes.count)" If ($Settings.remediate -eq $true) { @@ -39,10 +39,10 @@ function Invoke-CIPPStandardDelegateSentItems { } } if ($Settings.alert -eq $true) { - if ($Mailboxes) { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Delegate Sent Items Style is not enabled for $($Mailboxes.count) mailboxes" -sev Alert + if ($null -eq $Mailboxes) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Delegate Sent Items Style is enabled for all mailboxes' -sev Info } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'Delegate Sent Items Style is enabled' -sev Info + Write-LogMessage -API 'Standards' -tenant $tenant -message "Delegate Sent Items Style is not enabled for $($Mailboxes.count) mailboxes" -sev Alert } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 index 902e545d8a30..157bf5fbf690 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 @@ -9,7 +9,7 @@ function Invoke-CIPPStandardDeletedUserRentention { If ($Settings.remediate -eq $true) { Write-Host 'Time to remediate' - + if ($StateSetCorrectly -eq $false) { try { $body = '{"deletedUserPersonalSiteRetentionPeriodInDays": 365}' diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 index d080ca55f0c5..dec70bd076ec 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 @@ -60,9 +60,8 @@ function Invoke-CIPPStandardDisableAddShortcutsToOneDrive { } try { - $OnMicrosoft = (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/domains?$top=999' -tenantid $tenant | - Where-Object -Property isInitial -EQ $true).id.split('.') | Select-Object -First 1 - $AdminUrl = "https://$($OnMicrosoft)-admin.sharepoint.com" + $tenantName = (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/sites/root' -tenantid $TenantFilter).id.Split('.')[0] + $AdminUrl = "https://$($tenantName)-admin.sharepoint.com" $graphRequest = @{ 'scope' = "$AdminURL/.default" 'tenantid' = $tenant diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAdditionalStorageProviders.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAdditionalStorageProviders.ps1 index c6bbb8932cb7..6612d7090240 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAdditionalStorageProviders.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAdditionalStorageProviders.ps1 @@ -34,4 +34,4 @@ function Invoke-CIPPStandardDisableAdditionalStorageProviders { if ($Settings.report -eq $true) { Add-CIPPBPAField -FieldName 'AdditionalStorageProvidersEnabled' -FieldValue $AdditionalStorageProvidersState.AdditionalStorageProvidersEnabled -StoreAs bool -Tenant $tenant } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 index edcba0f5ff1b..ed8a7b256ff7 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 @@ -57,9 +57,9 @@ function Invoke-CIPPStandardDisableBasicAuthSMTP { Write-LogMessage -API 'Standards' -tenant $tenant -message $LogMessage -sev Alert } } - + if ($Settings.report -eq $true) { - + if ($CurrentInfo.SmtpClientAuthenticationDisabled -and $SMTPusers.Count -eq 0) { Add-CIPPBPAField -FieldName 'DisableBasicAuthSMTP' -FieldValue $CurrentInfo.SmtpClientAuthenticationDisabled -StoreAs bool -Tenant $tenant } else { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExternalCalendarSharing.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExternalCalendarSharing.ps1 index 85d66408b501..2393e7c3994d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExternalCalendarSharing.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExternalCalendarSharing.ps1 @@ -36,4 +36,4 @@ function Invoke-CIPPStandardDisableExternalCalendarSharing { $CurrentInfo.Enabled = -not $CurrentInfo.Enabled Add-CIPPBPAField -FieldName 'ExternalCalendarSharingDisabled' -FieldValue $CurrentInfo.Enabled -StoreAs bool -Tenant $tenant } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 index 63da951024d9..230920781a6a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 @@ -49,7 +49,7 @@ function Invoke-CIPPStandardDisableOutlookAddins { } } if ($Settings.report -eq $true) { - if ($RolesToRemove) { $State = $false } else { $State = $true } + $State = if ($RolesToRemove) { $false } else { $true } Add-CIPPBPAField -FieldName 'DisabledOutlookAddins' -FieldValue $State -StoreAs bool -Tenant $tenant } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSelfServiceLicenses.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSelfServiceLicenses.ps1 index c90b55962a58..6431f6053dc5 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSelfServiceLicenses.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSelfServiceLicenses.ps1 @@ -3,7 +3,7 @@ function Invoke-CIPPStandardDisableSelfServiceLicenses { .FUNCTIONALITY Internal #> - param($Tenant, $Settings) + param($Tenant, $Settings) Write-LogMessage -API 'Standards' -tenant $tenant -message 'Self Service Licenses cannot be disabled' -sev Error diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharedMailbox.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharedMailbox.ps1 index 96ac8e55a51b..d9d3356eba00 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharedMailbox.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharedMailbox.ps1 @@ -4,9 +4,11 @@ function Invoke-CIPPStandardDisableSharedMailbox { Internal #> param($Tenant, $Settings) - $SharedMailboxList = (New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($Tenant)/Mailbox?`$filter=ExchangeUserAccountControl ne 'accountdisabled'" -Tenantid $tenant -scope ExchangeOnline | Where-Object { $_.RecipientTypeDetails -EQ 'SharedMailbox' -or $_.RecipientTypeDetails -eq 'SchedulingMailbox' }) + $UserList = New-GraphGetRequest -uri 'https://graph.microsoft.com/v1.0/users?$top=999&$filter=accountEnabled eq true' -Tenantid $tenant -scope 'https://graph.microsoft.com/.default' + $SharedMailboxList = (New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($Tenant)/Mailbox" -Tenantid $tenant -scope ExchangeOnline | Where-Object { $_.RecipientTypeDetails -EQ 'SharedMailbox' -or $_.RecipientTypeDetails -eq 'SchedulingMailbox' -and $_.UserPrincipalName -in $UserList.UserPrincipalName }) If ($Settings.remediate -eq $true) { + if ($SharedMailboxList) { $SharedMailboxList | ForEach-Object { try { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 index edf707f9fc76..022f21807864 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 @@ -36,4 +36,4 @@ function Invoke-CIPPStandardDisableTNEF { Add-CIPPBPAField -FieldName 'TNEFDisabled' -FieldValue $State -StoreAs bool -Tenant $tenant } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 index 46a01eb94b90..97bac09d7668 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 @@ -35,4 +35,4 @@ function Invoke-CIPPStandardDisableUserSiteCreate { if ($Settings.report -eq $true) { Add-CIPPBPAField -FieldName 'DisableUserSiteCreate' -FieldValue $CurrentInfo.isSiteCreationEnabled -StoreAs bool -Tenant $tenant } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableViva.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableViva.ps1 index fe61f3fb3968..2a87da3fef09 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableViva.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableViva.ps1 @@ -4,18 +4,19 @@ function Invoke-CIPPStandardDisableViva { Internal #> param($Tenant, $Settings) + try { # TODO This does not work without Global Admin permissions for some reason. Throws an "EXCEPTION: Tenant admin role is required" error. -Bobby $CurrentSetting = New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/organization/$Tenant/settings/peopleInsights" -tenantid $Tenant -AsApp $true } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to get Viva insights settings. Error: $ErrorMessage" -sev Error - Exit + Return } - + If ($Settings.remediate -eq $true) { Write-Host 'Time to remediate' - + if ($CurrentSetting.isEnabledInOrganization -eq $false) { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Viva is already disabled.' -sev Info } else { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 index 05ab9cfbd117..52d3e3294c18 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 @@ -37,4 +37,4 @@ function Invoke-CIPPStandardEnableMailTips { Add-CIPPBPAField -FieldName 'MailTipsEnabled' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 index 9181ae888e66..2374206fc6d0 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 @@ -90,4 +90,4 @@ function Invoke-CIPPStandardEnableMailboxAuditing { Add-CIPPBPAField -FieldName 'MailboxAuditingEnabled' -FieldValue $AuditState -StoreAs bool -Tenant $Tenant } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnablePronouns.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnablePronouns.ps1 index 56d5c8a1815e..bd4d6c85e70e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnablePronouns.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnablePronouns.ps1 @@ -11,7 +11,7 @@ function Invoke-CIPPStandardEnablePronouns { } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message Write-LogMessage -API 'Standards' -tenant $Tenant -message "Could not get CurrentState for Pronouns. Error: $ErrorMessage" -sev Error - Exit + Return } Write-Host $CurrentState @@ -34,19 +34,16 @@ function Invoke-CIPPStandardEnablePronouns { } if ($Settings.alert -eq $true) { - + if ($CurrentState.isEnabledInOrganization -eq $true) { Write-LogMessage -API 'Standards' -tenant $tenant -message 'Pronouns are enabled.' -sev Info } else { Write-LogMessage -API 'Standards' -tenant $tenant -message 'Pronouns are not enabled.' -sev Alert } - } if ($Settings.report -eq $true) { - + Add-CIPPBPAField -FieldName 'PronounsEnabled' -FieldValue $CurrentState.isEnabledInOrganization -StoreAs bool -Tenant $tenant - } - -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExConnector.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExConnector.ps1 index 275cda358879..84a3258ad940 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExConnector.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExConnector.ps1 @@ -1,35 +1,35 @@ function Invoke-CIPPStandardExConnector { - <# + <# .FUNCTIONALITY Internal #> - param($Tenant, $Settings) - If ($Settings.remediate -eq $true) { + param($Tenant, $Settings) + If ($Settings.remediate -eq $true) { + + $APINAME = 'Standards' + foreach ($Template in $Settings.TemplateList) { + try { + $Table = Get-CippTable -tablename 'templates' + $Filter = "PartitionKey eq 'ExConnectorTemplate' and RowKey eq '$($Template.value)'" + $connectorType = (Get-AzDataTableEntity @Table -Filter $Filter).direction + $RequestParams = (Get-AzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json + $Existing = New-ExoRequest -ErrorAction SilentlyContinue -tenantid $Tenant -cmdlet "Get-$($ConnectorType)connector" | Where-Object -Property Identity -EQ $RequestParams.name + if ($Existing) { + $RequestParams | Add-Member -NotePropertyValue $Existing.Identity -NotePropertyName Identity -Force + $null = New-ExoRequest -tenantid $Tenant -cmdlet "Set-$($ConnectorType)connector" -cmdParams $RequestParams -useSystemMailbox $true + Write-LogMessage -API $APINAME -tenant $Tenant -message "Updated transport rule for $($Tenant, $Settings)" -sev info + } else { + $null = New-ExoRequest -tenantid $Tenant -cmdlet "New-$($ConnectorType)connector" -cmdParams $RequestParams -useSystemMailbox $true + Write-LogMessage -API $APINAME -tenant $Tenant -message "Created transport rule for $($Tenant, $Settings)" -sev info + } + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create or update Exchange Connector Rule: $ErrorMessage" -sev 'Error' + } - $APINAME = 'Standards' - foreach ($Template in $Settings.TemplateList) { - try { - $Table = Get-CippTable -tablename 'templates' - $Filter = "PartitionKey eq 'ExConnectorTemplate' and RowKey eq '$($Template.value)'" - $connectorType = (Get-AzDataTableEntity @Table -Filter $Filter).direction - $RequestParams = (Get-AzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json - $Existing = New-ExoRequest -ErrorAction SilentlyContinue -tenantid $Tenant -cmdlet "Get-$($ConnectorType)connector" | Where-Object -Property Identity -EQ $RequestParams.name - if ($Existing) { - $RequestParams | Add-Member -NotePropertyValue $Existing.Identity -NotePropertyName Identity -Force - $GraphRequest = New-ExoRequest -tenantid $Tenant -cmdlet "Set-$($ConnectorType)connector" -cmdParams $RequestParams -useSystemMailbox $true - Write-LogMessage -API $APINAME -tenant $Tenant -message "Updated transport rule for $($Tenant, $Settings)" -sev info - } else { - $GraphRequest = New-ExoRequest -tenantid $Tenant -cmdlet "New-$($ConnectorType)connector" -cmdParams $RequestParams -useSystemMailbox $true - Write-LogMessage -API $APINAME -tenant $Tenant -message "Created transport rule for $($Tenant, $Settings)" -sev info } - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create or update Exchange Connector Rule: $ErrorMessage" -sev 'Error' - } } - } - } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 index 56b2338a6b8c..6fefb63e5b59 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 @@ -9,6 +9,17 @@ function Invoke-CIPPStandardExternalMFATrusted { $WantedState = if ($Settings.state -eq 'true') { $true } else { $false } $StateMessage = if ($WantedState) { 'enabled' } else { 'disabled' } + if ($Settings.report -eq $true) { + + Add-CIPPBPAField -FieldName 'ExternalMFATrusted' -FieldValue $ExternalMFATrusted.inboundTrust.isMfaAccepted -StoreAs bool -Tenant $tenant + } + + # Input validation + if (([string]::IsNullOrWhiteSpace($Settings.state) -or $Settings.state -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'ExternalMFATrusted: Invalid state parameter set' -sev Error + Return + } + if ($Settings.remediate -eq $true) { Write-Host 'Remediate External MFA Trusted' @@ -35,11 +46,5 @@ function Invoke-CIPPStandardExternalMFATrusted { } else { Write-LogMessage -API 'Standards' -tenant $tenant -message "External MFA Trusted is not $StateMessage." -sev Alert } - - } - - if ($Settings.report -eq $true) { - - Add-CIPPBPAField -FieldName 'ExternalMFATrusted' -FieldValue $ExternalMFATrusted.inboundTrust.isMfaAccepted -StoreAs bool -Tenant $tenant } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 index 0da2ddbedc03..6dccab45117f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 @@ -5,10 +5,10 @@ function Invoke-CIPPStandardFocusedInbox { #> param($Tenant, $Settings) - # Exit if the wanted state is not valid - if ($Settings.state -ne 'enabled' -and $Settings.state -ne 'disabled') { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Invalid state for Focused Inbox. Please select either "enabled" or "disabled".' -sev Error - Exit + # Input validation + if ([string]::IsNullOrWhiteSpace($Settings.state) -or $Settings.state -eq 'Select a value') { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'ExternalMFATrusted: Invalid state parameter set' -sev Error + Return } $CurrentState = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig').FocusedInboxOn @@ -44,4 +44,4 @@ function Invoke-CIPPStandardFocusedInbox { if ($Settings.report -eq $true) { Add-CIPPBPAField -FieldName 'FocusedInboxCorrectState' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 index 3f8d24cf35b8..583a39ecb8f8 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 @@ -5,18 +5,9 @@ function Invoke-CIPPStandardGlobalQuarantineNotifications { #> param ($Tenant, $Settings) - # Exit if invalid state in the frontend is selected - try { - $WantedState = [timespan]$Settings.NotificationInterval - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Invalid state selected for Global Quarantine Notifications. Error: $ErrorMessage" -sev Error - Exit - } - $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-QuarantinePolicy' -cmdParams @{ QuarantinePolicyType = 'GlobalQuarantinePolicy' } - # This might take the cake on ugly hacky stuff i've done, + # This might take the cake on ugly hacky stuff i've done, # but i just cant understand why the API returns the values it does and not a timespan like the equivalent powershell command does # If you know why, please let me know -Bobby $CurrentState.EndUserSpamNotificationFrequency = switch ($CurrentState.EndUserSpamNotificationFrequency) { @@ -26,6 +17,19 @@ function Invoke-CIPPStandardGlobalQuarantineNotifications { Default { $null } } + if ($Settings.report -eq $true) { + + Add-CIPPBPAField -FieldName 'GlobalQuarantineNotificationsSet' -FieldValue [string]$CurrentState.EndUserSpamNotificationFrequency -StoreAs string -Tenant $tenant + } + # Input validation + try { + $WantedState = [timespan]$Settings.NotificationInterval + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Invalid state selected for Global Quarantine Notifications. Error: $ErrorMessage" -sev Error + Return + } + if ($Settings.remediate -eq $true) { Write-Host 'Time to remediate' @@ -43,16 +47,11 @@ function Invoke-CIPPStandardGlobalQuarantineNotifications { } if ($Settings.alert -eq $true) { - + if ($CurrentState.EndUserSpamNotificationFrequency -eq $WantedState) { Write-LogMessage -API 'Standards' -tenant $tenant -message "Global Quarantine Notifications are set to the desired value of $WantedState" -sev Info } else { Write-LogMessage -API 'Standards' -tenant $tenant -message "Global Quarantine Notifications are not set to the desired value of $WantedState" -sev Alert } } - - if ($Settings.report -eq $true) { - - Add-CIPPBPAField -FieldName 'GlobalQuarantineNotificationsSet' -FieldValue [string]$CurrentState.EndUserSpamNotificationFrequency -StoreAs string -Tenant $tenant - } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 index 0249bc747b42..4c1aeeebc2de 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 @@ -1,68 +1,68 @@ function Invoke-CIPPStandardGroupTemplate { - <# + <# .FUNCTIONALITY Internal #> - param($Tenant, $Settings) - If ($Settings.remediate -eq $true) { + param($Tenant, $Settings) + If ($Settings.remediate -eq $true) { - foreach ($Template in $Settings.TemplateList) { - try { - $Table = Get-CippTable -tablename 'templates' - $Filter = "PartitionKey eq 'GroupTemplate' and RowKey eq '$($Template.value)'" - $groupobj = (Get-AzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json - $email = if ($groupobj.domain) { "$($groupobj.username)@$($groupobj.domain)" } else { "$($groupobj.username)@$($Tenant)" } - $CheckExististing = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/groups' -tenantid $tenant | Where-Object -Property displayName -EQ $groupobj.displayname - if (!$CheckExististing) { - if ($groupobj.groupType -in 'Generic', 'azurerole', 'dynamic') { + foreach ($Template in $Settings.TemplateList) { + try { + $Table = Get-CippTable -tablename 'templates' + $Filter = "PartitionKey eq 'GroupTemplate' and RowKey eq '$($Template.value)'" + $groupobj = (Get-AzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json + $email = if ($groupobj.domain) { "$($groupobj.username)@$($groupobj.domain)" } else { "$($groupobj.username)@$($Tenant)" } + $CheckExististing = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/groups' -tenantid $tenant | Where-Object -Property displayName -EQ $groupobj.displayname + if (!$CheckExististing) { + if ($groupobj.groupType -in 'Generic', 'azurerole', 'dynamic') { - $BodyToship = [pscustomobject] @{ - 'displayName' = $groupobj.Displayname - 'description' = $groupobj.Description - 'mailNickname' = $groupobj.username - mailEnabled = [bool]$false - securityEnabled = [bool]$true - isAssignableToRole = [bool]($groupobj | Where-Object -Property groupType -EQ 'AzureRole') + $BodyToship = [pscustomobject] @{ + 'displayName' = $groupobj.Displayname + 'description' = $groupobj.Description + 'mailNickname' = $groupobj.username + mailEnabled = [bool]$false + securityEnabled = [bool]$true + isAssignableToRole = [bool]($groupobj | Where-Object -Property groupType -EQ 'AzureRole') - } - if ($groupobj.membershipRules) { - $BodyToship | Add-Member -NotePropertyName 'membershipRule' -NotePropertyValue ($groupobj.membershipRules) - $BodyToship | Add-Member -NotePropertyName 'groupTypes' -NotePropertyValue @('DynamicMembership') - $BodyToship | Add-Member -NotePropertyName 'membershipRuleProcessingState' -NotePropertyValue 'On' - } - $GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/groups' -tenantid $tenant -type POST -body (ConvertTo-Json -InputObject $BodyToship -Depth 10) -verbose - } else { - if ($groupobj.groupType -eq 'dynamicdistribution') { - $Params = @{ - Name = $groupobj.Displayname - RecipientFilter = $groupobj.membershipRules - PrimarySmtpAddress = $email - } - $GraphRequest = New-ExoRequest -tenantid $tenant -cmdlet 'New-DynamicDistributionGroup' -cmdParams $params - } else { - $Params = @{ - Name = $groupobj.Displayname - Alias = $groupobj.username - Description = $groupobj.Description - PrimarySmtpAddress = $email - Type = $groupobj.groupType - RequireSenderAuthenticationEnabled = [bool]!$groupobj.AllowExternal - } - $GraphRequest = New-ExoRequest -tenantid $tenant -cmdlet 'New-DistributionGroup' -cmdParams $params - } - } - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API 'Standards' -tenant $tenant -message "Created group $($groupobj.displayname) with id $($GraphRequest.id) " -Sev 'Info' + } + if ($groupobj.membershipRules) { + $BodyToship | Add-Member -NotePropertyName 'membershipRule' -NotePropertyValue ($groupobj.membershipRules) + $BodyToship | Add-Member -NotePropertyName 'groupTypes' -NotePropertyValue @('DynamicMembership') + $BodyToship | Add-Member -NotePropertyName 'membershipRuleProcessingState' -NotePropertyValue 'On' + } + $GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/groups' -tenantid $tenant -type POST -body (ConvertTo-Json -InputObject $BodyToship -Depth 10) -verbose + } else { + if ($groupobj.groupType -eq 'dynamicdistribution') { + $Params = @{ + Name = $groupobj.Displayname + RecipientFilter = $groupobj.membershipRules + PrimarySmtpAddress = $email + } + $GraphRequest = New-ExoRequest -tenantid $tenant -cmdlet 'New-DynamicDistributionGroup' -cmdParams $params + } else { + $Params = @{ + Name = $groupobj.Displayname + Alias = $groupobj.username + Description = $groupobj.Description + PrimarySmtpAddress = $email + Type = $groupobj.groupType + RequireSenderAuthenticationEnabled = [bool]!$groupobj.AllowExternal + } + $GraphRequest = New-ExoRequest -tenantid $tenant -cmdlet 'New-DistributionGroup' -cmdParams $params + } + } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API 'Standards' -tenant $tenant -message "Created group $($groupobj.displayname) with id $($GraphRequest.id) " -Sev 'Info' - } else { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API 'Standards' -tenant $tenant -message "Group exists $($groupobj.displayname). Did not create" -Sev 'Info' + } else { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API 'Standards' -tenant $tenant -message "Group exists $($groupobj.displayname). Did not create" -Sev 'Info' + } + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create group: $ErrorMessage" -sev 'Error' + } } - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create group: $ErrorMessage" -sev 'Error' - } - } - } + } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 index 9263b386bb23..66f253ef721c 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 @@ -1,129 +1,129 @@ function Invoke-CIPPStandardIntuneTemplate { - <# + <# .FUNCTIONALITY Internal #> - param($Tenant, $Settings) - If ($Settings.remediate -eq $true) { + param($Tenant, $Settings) + If ($Settings.remediate -eq $true) { - Write-Host 'starting template deploy' - $APINAME = 'Standards' - foreach ($Template in $Settings.TemplateList) { - Write-Host 'working on template deploy' - try { - $Table = Get-CippTable -tablename 'templates' - $Filter = "PartitionKey eq 'IntuneTemplate'" - $Request = @{body = $null } - $Request.body = (Get-AzDataTableEntity @Table -Filter $Filter | Where-Object -Property RowKey -Like "$($template.value)*").JSON | ConvertFrom-Json - $displayname = $request.body.Displayname - $description = $request.body.Description - $RawJSON = $Request.body.RawJSON + Write-Host 'starting template deploy' + $APINAME = 'Standards' + foreach ($Template in $Settings.TemplateList) { + Write-Host 'working on template deploy' + try { + $Table = Get-CippTable -tablename 'templates' + $Filter = "PartitionKey eq 'IntuneTemplate'" + $Request = @{body = $null } + $Request.body = (Get-AzDataTableEntity @Table -Filter $Filter | Where-Object -Property RowKey -Like "$($template.value)*").JSON | ConvertFrom-Json + $displayname = $request.body.Displayname + $description = $request.body.Description + $RawJSON = $Request.body.RawJSON - switch ($Request.body.Type) { - 'AppProtection' { - $TemplateType = ($RawJSON | ConvertFrom-Json).'@odata.type' -replace '#microsoft.graph.', '' - $TemplateTypeURL = "$($TemplateType)s" - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/$TemplateTypeURL" -tenantid $tenant - if ($displayname -in $CheckExististing.displayName) { - $ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $PolicyName - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenant -type PATCH -body $RawJSON - } else { - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON - } - } - 'deviceCompliancePolicies' { - $TemplateTypeURL = 'deviceCompliancePolicies' - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant + switch ($Request.body.Type) { + 'AppProtection' { + $TemplateType = ($RawJSON | ConvertFrom-Json).'@odata.type' -replace '#microsoft.graph.', '' + $TemplateTypeURL = "$($TemplateType)s" + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/$TemplateTypeURL" -tenantid $tenant + if ($displayname -in $CheckExististing.displayName) { + $ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $PolicyName + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenant -type PATCH -body $RawJSON + } else { + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON + } + } + 'deviceCompliancePolicies' { + $TemplateTypeURL = 'deviceCompliancePolicies' + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant - $JSON = $RawJSON | ConvertFrom-Json | Select-Object * -ExcludeProperty id, createdDateTime, lastModifiedDateTime, version, 'scheduledActionsForRule@odata.context', '@odata.context' - $JSON.scheduledActionsForRule = @($JSON.scheduledActionsForRule | Select-Object * -ExcludeProperty 'scheduledActionConfigurations@odata.context') - $RawJSON = ConvertTo-Json -InputObject $JSON -Depth 20 -Compress - Write-Host $RawJSON - if ($displayname -in $CheckExististing.displayName) { - $ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $PolicyName - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenant -type PATCH -body $RawJSON - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Updated policy $($PolicyName) to template defaults" -Sev 'info' - } else { - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($PolicyName) via template" -Sev 'info' - } - } - 'Admin' { - $TemplateTypeURL = 'groupPolicyConfigurations' - $CreateBody = '{"description":"' + $description + '","displayName":"' + $displayname + '","roleScopeTagIds":["0"]}' - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant - if ($displayname -in $CheckExististing.displayName) { - $ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $displayname - $ExistingData = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($existingId.id)')/definitionValues" -tenantid $tenant - $DeleteJson = $RawJSON | ConvertFrom-Json -Depth 10 - $DeleteJson.deletedIds = @($ExistingData.id) - $DeleteJson.added = @() - $DeleteJson = ConvertTo-Json -Depth 10 -InputObject $DeleteJson - $DeleteRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($existingId.id)')/updateDefinitionValues" -tenantid $tenant -type POST -body $DeleteJson - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($existingId.id)')/updateDefinitionValues" -tenantid $tenant -type POST -body $RawJSON - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Updated policy $($Displayname) to template defaults" -Sev 'info' + $JSON = $RawJSON | ConvertFrom-Json | Select-Object * -ExcludeProperty id, createdDateTime, lastModifiedDateTime, version, 'scheduledActionsForRule@odata.context', '@odata.context' + $JSON.scheduledActionsForRule = @($JSON.scheduledActionsForRule | Select-Object * -ExcludeProperty 'scheduledActionConfigurations@odata.context') + $RawJSON = ConvertTo-Json -InputObject $JSON -Depth 20 -Compress + Write-Host $RawJSON + if ($displayname -in $CheckExististing.displayName) { + $ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $PolicyName + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenant -type PATCH -body $RawJSON + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Updated policy $($PolicyName) to template defaults" -Sev 'info' + } else { + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($PolicyName) via template" -Sev 'info' + } + } + 'Admin' { + $TemplateTypeURL = 'groupPolicyConfigurations' + $CreateBody = '{"description":"' + $description + '","displayName":"' + $displayname + '","roleScopeTagIds":["0"]}' + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant + if ($displayname -in $CheckExististing.displayName) { + $ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $displayname + $ExistingData = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($existingId.id)')/definitionValues" -tenantid $tenant + $DeleteJson = $RawJSON | ConvertFrom-Json -Depth 10 + $DeleteJson.deletedIds = @($ExistingData.id) + $DeleteJson.added = @() + $DeleteJson = ConvertTo-Json -Depth 10 -InputObject $DeleteJson + $DeleteRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($existingId.id)')/updateDefinitionValues" -tenantid $tenant -type POST -body $DeleteJson + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($existingId.id)')/updateDefinitionValues" -tenantid $tenant -type POST -body $RawJSON + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Updated policy $($Displayname) to template defaults" -Sev 'info' - } else { - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $CreateBody - $UpdateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($CreateRequest.id)')/updateDefinitionValues" -tenantid $tenant -type POST -body $RawJSON - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($Displayname) to template defaults" -Sev 'info' + } else { + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $CreateBody + $UpdateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($CreateRequest.id)')/updateDefinitionValues" -tenantid $tenant -type POST -body $RawJSON + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($Displayname) to template defaults" -Sev 'info' - } - } - 'Device' { - $TemplateTypeURL = 'deviceConfigurations' - $PolicyName = ($RawJSON | ConvertFrom-Json).displayName - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant - if ($PolicyName -in $CheckExististing.displayName) { - $ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $PolicyName - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenant -type PATCH -body $RawJSON - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Updated policy $($PolicyName) to template defaults" -Sev 'info' + } + } + 'Device' { + $TemplateTypeURL = 'deviceConfigurations' + $PolicyName = ($RawJSON | ConvertFrom-Json).displayName + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant + if ($PolicyName -in $CheckExististing.displayName) { + $ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $PolicyName + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenant -type PATCH -body $RawJSON + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Updated policy $($PolicyName) to template defaults" -Sev 'info' - } else { - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($PolicyName) via template" -Sev 'info' + } else { + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($PolicyName) via template" -Sev 'info' - } - } - 'Catalog' { - $TemplateTypeURL = 'configurationPolicies' - $PolicyName = ($RawJSON | ConvertFrom-Json).Name - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant - if ($PolicyName -in $CheckExististing.name) { - $ExistingID = $CheckExististing | Where-Object -Property Name -EQ $PolicyName - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenant -type PUT -body $RawJSON + } + } + 'Catalog' { + $TemplateTypeURL = 'configurationPolicies' + $PolicyName = ($RawJSON | ConvertFrom-Json).Name + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant + if ($PolicyName -in $CheckExististing.name) { + $ExistingID = $CheckExististing | Where-Object -Property Name -EQ $PolicyName + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenant -type PUT -body $RawJSON - } else { - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($PolicyName) via template" -Sev 'info' - } - } - 'windowsDriverUpdateProfiles' { - $TemplateTypeURL = 'windowsDriverUpdateProfiles' - $PolicyName = ($RawJSON | ConvertFrom-Json).Name - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant - if ($PolicyName -in $CheckExististing.name) { - $ExistingID = $CheckExististing | Where-Object -Property Name -EQ $PolicyName - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenant -type PUT -body $RawJSON + } else { + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($PolicyName) via template" -Sev 'info' + } + } + 'windowsDriverUpdateProfiles' { + $TemplateTypeURL = 'windowsDriverUpdateProfiles' + $PolicyName = ($RawJSON | ConvertFrom-Json).Name + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant + if ($PolicyName -in $CheckExististing.name) { + $ExistingID = $CheckExististing | Where-Object -Property Name -EQ $PolicyName + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenant -type PUT -body $RawJSON - } else { - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($PolicyName) via template" -Sev 'info' - } - } + } else { + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenant -type POST -body $RawJSON + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $($Tenant) -message "Added policy $($PolicyName) via template" -Sev 'info' + } + } - } + } - if ($Settings.AssignTo) { - Write-Host "Assigning Policy to $($Settings.AssignTo) the create ID is $($CreateRequest)" - if ($Settings.AssignTo -eq 'customGroup') { $Settings.AssignTo = $Settings.customGroup } - Set-CIPPAssignedPolicy -PolicyId $CreateRequest.id -TenantFilter $tenant -GroupName $Settings.AssignTo -Type $TemplateTypeURL + if ($Settings.AssignTo) { + Write-Host "Assigning Policy to $($Settings.AssignTo) the create ID is $($CreateRequest)" + if ($Settings.AssignTo -eq 'customGroup') { $Settings.AssignTo = $Settings.customGroup } + Set-CIPPAssignedPolicy -PolicyId $CreateRequest.id -TenantFilter $tenant -GroupName $Settings.AssignTo -Type $TemplateTypeURL + } + Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully added Intune Template policy for $($Tenant)" -sev 'Info' + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create or update Intune Template: $ErrorMessage" -sev 'Error' + } } - Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully added Intune Template policy for $($Tenant)" -sev 'Info' - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create or update Intune Template: $ErrorMessage" -sev 'Error' - } } - } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMailContacts.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMailContacts.ps1 index 563e76cdc4ff..8cc14082f3a3 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMailContacts.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMailContacts.ps1 @@ -11,7 +11,6 @@ function Invoke-CIPPStandardMailContacts { If ($Settings.remediate -eq $true) { - # TODO: Make this smaller if possible if ($CurrentInfo.marketingNotificationEmails -eq $Contacts.MarketingContact -and ` ($CurrentInfo.securityComplianceNotificationMails -in $TechAndSecurityContacts -or $CurrentInfo.technicalNotificationMails -in $TechAndSecurityContacts) -and ` diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 index d9ae65ac222f..5a3e99aa57ad 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 @@ -27,7 +27,7 @@ function Invoke-CIPPStandardMalwareFilterPolicy { $RuleState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-MalwareFilterRule' | Where-Object -Property Name -EQ "CIPP $PolicyName" | Select-Object Name, MalwareFilterPolicy, Priority, RecipientDomainIs - + $RuleStateIsCorrect = ($RuleState.Name -eq "CIPP $PolicyName") -and ($RuleState.MalwareFilterPolicy -eq $PolicyName) -and ($RuleState.Priority -eq 0) -and diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 index e3c7d190e072..6d387b212767 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 @@ -4,10 +4,29 @@ function Invoke-CIPPStandardNudgeMFA { Internal #> param($Tenant, $Settings) + $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy' -tenantid $Tenant $State = if ($CurrentInfo.registrationEnforcement.authenticationMethodsRegistrationCampaign.state -eq 'enabled') { $true } else { $false } + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'NudgeMFA' -FieldValue $State -StoreAs bool -Tenant $tenant + } + + + # Input validation + if (([string]::IsNullOrWhiteSpace($Settings.state) -or $Settings.state -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'NudgeMFA: Invalid state parameter set' -sev Error + Return + } + # Input validation + if (($Settings.snoozeDurationInDays -lt 0 -or $Settings.snoozeDurationInDays -gt 15) -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'NudgeMFA: Invalid snoozeDurationInDays parameter set' -sev Error + Return + } + + If ($Settings.remediate -eq $true) { + $StateName = $Settings.state.Substring(0, 1).ToUpper() + $Settings.state.Substring(1) if ($Settings.state -ne $CurrentInfo.registrationEnforcement.authenticationMethodsRegistrationCampaign.state -or $Settings.snoozeDurationInDays -ne $CurrentInfo.registrationEnforcement.authenticationMethodsRegistrationCampaign.snoozeDurationInDays) { try { @@ -37,8 +56,4 @@ function Invoke-CIPPStandardNudgeMFA { Write-LogMessage -API 'Standards' -tenant $tenant -message "Authenticator App Nudge is not enabled with a snooze duration of $($CurrentInfo.registrationEnforcement.authenticationMethodsRegistrationCampaign.snoozeDurationInDays)" -sev Alert } } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'NudgeMFA' -FieldValue $State -StoreAs bool -Tenant $tenant - } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 index d62e02a3a223..38d2b41dfce3 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 @@ -27,7 +27,7 @@ function Invoke-CIPPStandardOauthConsent { } New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' -Type PATCH -Body '{"permissionGrantPolicyIdsAssignedToDefaultUserRole":["managePermissionGrantsForSelf.cipp-consent-policy"]}' -ContentType 'application/json' } - + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Application Consent Mode has been enabled.' -sev Info } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 index 22a46a14a2e4..c2e3c7a687b7 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 @@ -4,9 +4,20 @@ function Invoke-CIPPStandardPWcompanionAppAllowedState { Internal #> param($Tenant, $Settings) + $authenticatorFeaturesState = (New-GraphGetRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator' -Type GET) $authstate = if ($authenticatorFeaturesState.featureSettings.companionAppAllowedState.state -eq 'enabled') { $true } else { $false } + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'companionAppAllowedState' -FieldValue $authstate -StoreAs bool -Tenant $tenant + } + + # Input validation + if (([string]::IsNullOrWhiteSpace($Settings.state) -or $Settings.state -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'PWcompanionAppAllowedState: Invalid state parameter set' -sev Error + Return + } + If ($Settings.remediate -eq $true) { if ($authenticatorFeaturesState.featureSettings.companionAppAllowedState.state -eq $Settings.state) { @@ -46,8 +57,4 @@ function Invoke-CIPPStandardPWcompanionAppAllowedState { Write-LogMessage -API 'Standards' -tenant $tenant -message 'companionAppAllowedState is not enabled.' -sev Alert } } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'companionAppAllowedState' -FieldValue $authstate -StoreAs bool -Tenant $tenant - } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 index 5c23a6763f8f..2f85c01bf859 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 @@ -26,4 +26,4 @@ function Invoke-CIPPStandardPWdisplayAppInformationRequiredState { if ($Settings.report -eq $true) { Add-CIPPBPAField -FieldName 'PWdisplayAppInformationRequiredState' -FieldValue $State -StoreAs bool -Tenant $tenant } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 index 1e0daba708c2..5cf8dac138a1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 @@ -42,4 +42,4 @@ function Invoke-CIPPStandardPasswordExpireDisabled { if ($Settings.report -eq $true) { Add-CIPPBPAField -FieldName 'PasswordExpireDisabled' -FieldValue $DomainswithoutPassExpire -StoreAs json -Tenant $tenant } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSSPR.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSSPR.ps1 index e6fbdd3181f6..ff39c3b17c39 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSSPR.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSSPR.ps1 @@ -1,10 +1,10 @@ function Invoke-CIPPStandardSSPR { - <# + <# .FUNCTIONALITY Internal #> - param($Tenant, $Settings) + param($Tenant, $Settings) - Write-LogMessage -API 'Standards' -tenant $tenant -message 'SSPR standard is no longer available' -sev Error + Write-LogMessage -API 'Standards' -tenant $tenant -message 'SSPR standard is no longer available' -sev Error } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 index 1973cb4efc10..78a49086fbd6 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 @@ -22,7 +22,7 @@ function Invoke-CIPPStandardSafeAttachmentPolicy { $RuleState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeAttachmentRule' | Where-Object -Property Name -EQ "CIPP $PolicyName" | Select-Object Name, SafeAttachmentPolicy, Priority, RecipientDomainIs - + $RuleStateIsCorrect = ($RuleState.Name -eq "CIPP $PolicyName") -and ($RuleState.SafeAttachmentPolicy -eq $PolicyName) -and ($RuleState.Priority -eq 0) -and @@ -55,12 +55,12 @@ function Invoke-CIPPStandardSafeAttachmentPolicy { Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Safe Attachment Policy. Error: $ErrorMessage" -sev Error } } - + if ($RuleStateIsCorrect -eq $false) { $cmdparams = @{ - SafeAttachmentPolicy = $PolicyName - Priority = 0 - RecipientDomainIs = $AcceptedDomains.Name + SafeAttachmentPolicy = $PolicyName + Priority = 0 + RecipientDomainIs = $AcceptedDomains.Name } try { @@ -93,4 +93,4 @@ function Invoke-CIPPStandardSafeAttachmentPolicy { Add-CIPPBPAField -FieldName 'SafeAttachmentPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 index bd353b32e485..cea984a20a4f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 @@ -28,7 +28,7 @@ function Invoke-CIPPStandardSafeLinksPolicy { $RuleState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeLinksRule' | Where-Object -Property Name -EQ "CIPP $PolicyName" | Select-Object Name, SafeLinksPolicy, Priority, RecipientDomainIs - + $RuleStateIsCorrect = ($RuleState.Name -eq "CIPP $PolicyName") -and ($RuleState.SafeLinksPolicy -eq $PolicyName) -and ($RuleState.Priority -eq 0) -and @@ -70,9 +70,9 @@ function Invoke-CIPPStandardSafeLinksPolicy { if ($RuleStateIsCorrect -eq $false) { $cmdparams = @{ - SafeLinksPolicy = $PolicyName - Priority = 0 - RecipientDomainIs = $AcceptedDomains.Name + SafeLinksPolicy = $PolicyName + Priority = 0 + RecipientDomainIs = $AcceptedDomains.Name } try { @@ -105,4 +105,4 @@ function Invoke-CIPPStandardSafeLinksPolicy { Add-CIPPBPAField -FieldName 'SafeLinksPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSecurityDefaults.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSecurityDefaults.ps1 index 10b41322367d..07bc25df5021 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSecurityDefaults.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSecurityDefaults.ps1 @@ -7,6 +7,7 @@ function Invoke-CIPPStandardSecurityDefaults { $SecureDefaultsState = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/identitySecurityDefaultsEnforcementPolicy' -tenantid $tenant) If ($Settings.remediate -eq $true) { + if ($SecureDefaultsState.IsEnabled -ne $true) { try { Write-Host "Secure Defaults is disabled. Enabling for $tenant" -ForegroundColor Yellow diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 index ef65fb0b9c56..68c7519f5e25 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 @@ -4,6 +4,20 @@ function Invoke-CIPPStandardSendReceiveLimitTenant { Internal #> param($Tenant, $Settings) + + # Input validation + if ($Settings.SendLimit -lt 1 -or $Settings.SendLimit -gt 150) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'SendReceiveLimitTenant: Invalid SendLimit parameter set' -sev Error + Return + } + + # Input validation + if ($Settings.ReceiveLimit -lt 1 -or $Settings.ReceiveLimit -gt 150) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'SendReceiveLimitTenant: Invalid ReceiveLimit parameter set' -sev Error + Return + } + + $AllMailBoxPlans = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-MailboxPlan' | Select-Object DisplayName, MaxSendSize, MaxReceiveSize, GUID $MaxSendSize = [int64]"$($Settings.SendLimit)MB" $MaxReceiveSize = [int64]"$($Settings.ReceiveLimit)MB" diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 index 4946b64e8b4b..f6605904777f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 @@ -8,17 +8,17 @@ function Invoke-CIPPStandardShortenMeetings { # Input validation if ([Int32]$Settings.DefaultMinutesToReduceShortEventsBy -lt 0 -or [Int32]$Settings.DefaultMinutesToReduceShortEventsBy -gt 29) { Write-LogMessage -API 'Standards' -tenant $tenant -message 'Invalid shorten meetings settings specified. DefaultMinutesToReduceShortEventsBy must be an integer between 0 and 29' -sev Error - Exit + Return } if ([Int32]$Settings.DefaultMinutesToReduceLongEventsBy -lt 0 -or [Int32]$Settings.DefaultMinutesToReduceLongEventsBy -gt 29) { Write-LogMessage -API 'Standards' -tenant $tenant -message 'Invalid shorten meetings settings specified. DefaultMinutesToReduceLongEventsBy must be an integer between 0 and 29' -sev Error - Exit + Return } - $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig' | + $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig' | Select-Object -Property ShortenEventScopeDefault, DefaultMinutesToReduceShortEventsBy, DefaultMinutesToReduceLongEventsBy - $CorrectState = if ($CurrentState.ShortenEventScopeDefault -eq $Settings.ShortenEventScopeDefault -and - $CurrentState.DefaultMinutesToReduceShortEventsBy -eq $Settings.DefaultMinutesToReduceShortEventsBy -and + $CorrectState = if ($CurrentState.ShortenEventScopeDefault -eq $Settings.ShortenEventScopeDefault -and + $CurrentState.DefaultMinutesToReduceShortEventsBy -eq $Settings.DefaultMinutesToReduceShortEventsBy -and $CurrentState.DefaultMinutesToReduceLongEventsBy -eq $Settings.DefaultMinutesToReduceLongEventsBy) { $true } else { $false } if ($Settings.remediate -eq $true) { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 index 54acd8ffed62..af9e03c6122c 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 @@ -4,12 +4,24 @@ function Invoke-CIPPStandardSpoofWarn { Internal #> param($Tenant, $Settings) + $CurrentInfo = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-ExternalInOutlook') + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'SpoofingWarnings' -FieldValue $CurrentInfo.Enabled -StoreAs bool -Tenant $tenant + } + + # Input validation + if (([string]::IsNullOrWhiteSpace($Settings.state) -or $Settings.state -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'SpoofWarn: Invalid state parameter set' -sev Error + Return + } + If ($Settings.remediate -eq $true) { $status = if ($Settings.enable -and $Settings.disable) { + # Handle pre standards v2.0 legacy settings when this was 2 separate standards Write-LogMessage -API 'Standards' -tenant $tenant -message 'You cannot both enable and disable the Spoof Warnings setting' -sev Error - Exit + Return } elseif ($Settings.state -eq 'enabled' -or $Settings.enable) { $true } else { $false } if ($CurrentInfo.Enabled -eq $status) { @@ -32,8 +44,4 @@ function Invoke-CIPPStandardSpoofWarn { Write-LogMessage -API 'Standards' -tenant $tenant -message 'Outlook external spoof warnings are not enabled.' -sev Alert } } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'SpoofingWarnings' -FieldValue $CurrentInfo.Enabled -StoreAs bool -Tenant $tenant - } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTAP.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTAP.ps1 index 72a851a8154e..ce9a3c95ef62 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTAP.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTAP.ps1 @@ -4,9 +4,20 @@ function Invoke-CIPPStandardTAP { Internal #> param($Tenant, $Settings) + $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authenticationmethodspolicy/authenticationMethodConfigurations/TemporaryAccessPass' -tenantid $Tenant $State = if ($CurrentInfo.state -eq 'enabled') { $true } else { $false } + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'TemporaryAccessPass' -FieldValue $State -StoreAs bool -Tenant $tenant + } + + # Input validation + if (([string]::IsNullOrWhiteSpace($Settings.state) -or $Settings.state -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'TAP: Invalid state parameter set' -sev Error + Return + } + If ($Settings.remediate -eq $true) { if ($State) { Write-LogMessage -API 'Standards' -tenant $tenant -message 'Temporary Access Passwords is already enabled.' -sev Info @@ -22,8 +33,4 @@ function Invoke-CIPPStandardTAP { Write-LogMessage -API 'Standards' -tenant $tenant -message 'Temporary Access Passwords is not enabled.' -sev Alert } } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'TemporaryAccessPass' -FieldValue $State -StoreAs bool -Tenant $tenant - } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 index 86509c52564b..615dd6e94237 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 @@ -5,16 +5,22 @@ function Invoke-CIPPStandardTeamsMeetingsByDefault { #> param($Tenant, $Settings) - # Input validation - if ([string]::isNullOrEmpty($Settings.state) -or $Settings.state -eq 'Select a value') { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'TeamsMeetingsByDefault: Invalid state parameter set' -sev Error - Exit - } - $CurrentState = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig').OnlineMeetingsByDefaultEnabled $WantedState = if ($Settings.state -eq 'true') { $true } else { $false } $StateIsCorrect = if ($CurrentState -eq $WantedState) { $true } else { $false } + if ($Settings.report -eq $true) { + # Default is not set, not set means it's enabled + if ($null -eq $CurrentState ) { $CurrentState = $true } + Add-CIPPBPAField -FieldName 'TeamsMeetingsByDefault' -FieldValue $CurrentState -StoreAs bool -Tenant $tenant + } + + # Input validation + if (([string]::IsNullOrWhiteSpace($Settings.state) -or $Settings.state -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'TeamsMeetingsByDefault: Invalid state parameter set' -sev Error + Return + } + if ($Settings.remediate -eq $true) { Write-Host 'Time to remediate' if ($StateIsCorrect -eq $false) { @@ -38,11 +44,4 @@ function Invoke-CIPPStandardTeamsMeetingsByDefault { Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant TeamsMeetingsByDefault is not set correctly to $($Settings.state)" -sev Alert } } - - if ($Settings.report -eq $true) { - # Default is not set, not set means it's enabled - if ($null -eq $CurrentState ) { $CurrentState = $true } - Add-CIPPBPAField -FieldName 'TeamsMeetingsByDefault' -FieldValue $CurrentState -StoreAs bool -Tenant $tenant - } - -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 index a9bb46c8f53e..c2651ae346a9 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 @@ -5,10 +5,21 @@ function Invoke-CIPPStandardTenantDefaultTimezone { #> param($Tenant, $Settings) + $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true $ExpectedTimezone = $Settings.Timezone.value $StateIsCorrect = $CurrentState.tenantDefaultTimezone -eq $ExpectedTimezone + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'TenantDefaultTimezone' -FieldValue $CurrentState.tenantDefaultTimezone -StoreAs string -Tenant $tenant + } + + # Input validation + if (([string]::IsNullOrWhiteSpace($Settings.Timezone) -or $Settings.Timezone -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'TenantDefaultTimezone: Invalid Timezone parameter set' -sev Error + Return + } + If ($Settings.remediate -eq $true) { if ($StateIsCorrect -eq $true) { Write-LogMessage -API 'Standards' -tenant $tenant -message "Tenant Default Timezone is already set to $ExpectedTimezone" -sev Info @@ -31,7 +42,4 @@ function Invoke-CIPPStandardTenantDefaultTimezone { Write-LogMessage -API 'Standards' -tenant $tenant -message 'Tenant Default Timezone is not set to the desired value.' -sev Alert } } - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'TenantDefaultTimezone' -FieldValue $CurrentState.tenantDefaultTimezone -StoreAs string -Tenant $tenant - } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 index c0c6e0d17db3..ad65a91db297 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 @@ -1,36 +1,37 @@ function Invoke-CIPPStandardTransportRuleTemplate { - <# + <# .FUNCTIONALITY Internal #> - param($Tenant, $Settings) - If ($Settings.remediate -eq $true) { + param($Tenant, $Settings) - foreach ($Template in $Settings.TemplateList) { - Write-Host "working on $($Template.value)" - $Table = Get-CippTable -tablename 'templates' - $Filter = "PartitionKey eq 'TransportTemplate' and RowKey eq '$($Template.value)'" - $RequestParams = (Get-AzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json - $Existing = New-ExoRequest -ErrorAction SilentlyContinue -tenantid $Tenant -cmdlet 'Get-TransportRule' -useSystemMailbox $true | Where-Object -Property Identity -EQ $RequestParams.name + If ($Settings.remediate -eq $true) { + foreach ($Template in $Settings.TemplateList) { + Write-Host "working on $($Template.value)" + $Table = Get-CippTable -tablename 'templates' + $Filter = "PartitionKey eq 'TransportTemplate' and RowKey eq '$($Template.value)'" + $RequestParams = (Get-AzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json + $Existing = New-ExoRequest -ErrorAction SilentlyContinue -tenantid $Tenant -cmdlet 'Get-TransportRule' -useSystemMailbox $true | Where-Object -Property Identity -EQ $RequestParams.name - try { - if ($Existing) { - Write-Host 'Found existing' - $RequestParams | Add-Member -NotePropertyValue $RequestParams.name -NotePropertyName Identity - $GraphRequest = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-TransportRule' -cmdParams ($RequestParams | Select-Object -Property * -ExcludeProperty GUID, Comments, HasSenderOverride, ExceptIfHasSenderOverride, ExceptIfMessageContainsDataClassifications, MessageContainsDataClassifications, UseLegacyRegex) -useSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully set transport rule for $tenant" -sev 'Info' - } else { - Write-Host 'Creating new' - $GraphRequest = New-ExoRequest -tenantid $Tenant -cmdlet 'New-TransportRule' -cmdParams ($RequestParams | Select-Object -Property * -ExcludeProperty GUID, Comments, HasSenderOverride, ExceptIfHasSenderOverride, ExceptIfMessageContainsDataClassifications, MessageContainsDataClassifications, UseLegacyRegex) -useSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully created transport rule for $tenant" -sev 'Info' - } - Write-LogMessage -API $APINAME -tenant $Tenant -message "Created transport rule for $($tenantfilter)" -sev 'Debug' - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Could not create transport rule for $($tenantfilter): $ErrorMessage" -sev 'Error' - } + try { + if ($Existing) { + Write-Host 'Found existing' + $RequestParams | Add-Member -NotePropertyValue $RequestParams.name -NotePropertyName Identity + $GraphRequest = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-TransportRule' -cmdParams ($RequestParams | Select-Object -Property * -ExcludeProperty GUID, Comments, HasSenderOverride, ExceptIfHasSenderOverride, ExceptIfMessageContainsDataClassifications, MessageContainsDataClassifications, UseLegacyRegex) -useSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully set transport rule for $tenant" -sev 'Info' + } else { + Write-Host 'Creating new' + $GraphRequest = New-ExoRequest -tenantid $Tenant -cmdlet 'New-TransportRule' -cmdParams ($RequestParams | Select-Object -Property * -ExcludeProperty GUID, Comments, HasSenderOverride, ExceptIfHasSenderOverride, ExceptIfMessageContainsDataClassifications, MessageContainsDataClassifications, UseLegacyRegex) -useSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully created transport rule for $tenant" -sev 'Info' + } + + Write-LogMessage -API $APINAME -tenant $Tenant -message "Created transport rule for $($tenantfilter)" -sev 'Debug' + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $tenant -message "Could not create transport rule for $($tenantfilter): $ErrorMessage" -sev 'Error' + } + } } - } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 index c4c15c525441..0d20abaeb57a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 @@ -4,8 +4,24 @@ function Invoke-CIPPStandardUserSubmissions { Internal #> param($Tenant, $Settings) + $Policy = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-ReportSubmissionPolicy' + if ($Settings.report -eq $true) { + if ($Policy.length -eq 0) { + Add-CIPPBPAField -FieldName 'UserSubmissionPolicy' -FieldValue $false -StoreAs bool -Tenant $tenant + } else { + Add-CIPPBPAField -FieldName 'UserSubmissionPolicy' -FieldValue $Policy.EnableReportToMicrosoft -StoreAs bool -Tenant $tenant + } + } + + # Input validation + if ([string]::IsNullOrWhiteSpace($Settings.state) -or $Settings.state -eq 'Select a value') { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'UserSubmissions: Invalid state parameter set' -sev Error + Return + } + + If ($Settings.remediate -eq $true) { $Status = if ($Settings.state -eq 'enable') { $true } else { $false } @@ -56,12 +72,4 @@ function Invoke-CIPPStandardUserSubmissions { } } } - - if ($Settings.report -eq $true) { - if ($Policy.length -eq 0) { - Add-CIPPBPAField -FieldName 'UserSubmissionPolicy' -FieldValue $false -StoreAs bool -Tenant $tenant - } else { - Add-CIPPBPAField -FieldName 'UserSubmissionPolicy' -FieldValue $Policy.EnableReportToMicrosoft -StoreAs bool -Tenant $tenant - } - } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOAuthTokens.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOAuthTokens.ps1 index c8fd2f64b9de..a5f43f175998 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOAuthTokens.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOAuthTokens.ps1 @@ -4,9 +4,22 @@ function Invoke-CIPPStandardallowOAuthTokens { Internal #> param($Tenant, $Settings) + $CurrentInfo = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/softwareOath' -tenantid $Tenant $State = if ($CurrentInfo.state -eq 'enabled') { $true } else { $false } + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'softwareOath' -FieldValue $State -StoreAs bool -Tenant $tenant + } + + # Input validation + if (([string]::IsNullOrWhiteSpace($Settings.state) -or $Settings.state -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'allowOAuthTokens: Invalid state parameter set' -sev Error + Return + } + + + If ($Settings.remediate -eq $true) { if ($State) { Write-LogMessage -API 'Standards' -tenant $tenant -message 'Software OTP/oAuth tokens is already enabled.' -sev Info @@ -24,7 +37,5 @@ function Invoke-CIPPStandardallowOAuthTokens { } } - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'softwareOath' -FieldValue $State -StoreAs bool -Tenant $tenant - } + } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOTPTokens.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOTPTokens.ps1 index 6f956358c711..8459fce1aadc 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOTPTokens.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOTPTokens.ps1 @@ -26,4 +26,4 @@ function Invoke-CIPPStandardallowOTPTokens { Add-CIPPBPAField -FieldName 'MSAuthenticator' -FieldValue $CurrentInfo.isSoftwareOathEnabled -StoreAs bool -Tenant $tenant } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 index 6c94488a32d8..491d35ab7eb5 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 @@ -5,6 +5,12 @@ function Invoke-CIPPStandardcalDefault { #> param($Tenant, $Settings, $QueueItem) + # Input validation + if ([string]::IsNullOrWhiteSpace($Settings.permissionlevel) -or $Settings.permissionlevel -eq 'Select a value') { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'calDefault: Invalid permissionlevel parameter set' -sev Error + Return + } + If ($Settings.remediate -eq $true) { $Mailboxes = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-Mailbox' | Sort-Object UserPrincipalName $TotalMailboxes = $Mailboxes.Count diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 index 8b1203113522..b096ade25384 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 @@ -35,4 +35,4 @@ function Invoke-CIPPStandarddisableMacSync { $CurrentInfo.isMacSyncAppEnabled = -not $CurrentInfo.isMacSyncAppEnabled Add-CIPPBPAField -FieldName 'MacSync' -FieldValue $CurrentInfo.isMacSyncAppEnabled -StoreAs bool -Tenant $tenant } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneBrandingProfile.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneBrandingProfile.ps1 new file mode 100644 index 000000000000..c049ebb95749 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneBrandingProfile.ps1 @@ -0,0 +1,67 @@ +function Invoke-CIPPStandardintuneBrandingProfile { + <# + .FUNCTIONALITY + Internal + #> + + param($Tenant, $Settings) + $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/deviceManagement/intuneBrandingProfiles/c3a59481-1bf2-46ce-94b3-66eec07a8d60/' -tenantid $Tenant -AsApp $true + + $StateIsCorrect = ((-not $Settings.displayName) -or ($CurrentState.displayName -eq $Settings.displayName)) -and + ((-not $Settings.showLogo) -or ($CurrentState.showLogo -eq $Settings.showLogo)) -and + ((-not $Settings.showDisplayNameNextToLogo) -or ($CurrentState.showDisplayNameNextToLogo -eq $Settings.showDisplayNameNextToLogo)) -and + ((-not $Settings.contactITName) -or ($CurrentState.contactITName -eq $Settings.contactITName)) -and + ((-not $Settings.contactITPhoneNumber) -or ($CurrentState.contactITPhoneNumber -eq $Settings.contactITPhoneNumber)) -and + ((-not $Settings.contactITEmailAddress) -or ($CurrentState.contactITEmailAddress -eq $Settings.contactITEmailAddress)) -and + ((-not $Settings.contactITNotes) -or ($CurrentState.contactITNotes -eq $Settings.contactITNotes)) -and + ((-not $Settings.onlineSupportSiteName) -or ($CurrentState.onlineSupportSiteName -eq $Settings.onlineSupportSiteName)) -and + ((-not $Settings.onlineSupportSiteUrl) -or ($CurrentState.onlineSupportSiteUrl -eq $Settings.onlineSupportSiteUrl)) -and + ((-not $Settings.privacyUrl) -or ($CurrentState.privacyUrl -eq $Settings.privacyUrl)) + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Intune Branding Profile is already correctly configured' -sev Info + } else { + $Body = @{} + if ($Settings.displayName) { $Body.displayName = $Settings.displayName } + if ($Settings.showLogo) { $Body.showLogo = $Settings.showLogo } + if ($Settings.showDisplayNameNextToLogo) { $Body.showDisplayNameNextToLogo = $Settings.showDisplayNameNextToLogo } + if ($Settings.contactITName) { $Body.contactITName = $Settings.contactITName } + if ($Settings.contactITPhoneNumber) { $Body.contactITPhoneNumber = $Settings.contactITPhoneNumber } + if ($Settings.contactITEmailAddress) { $Body.contactITEmailAddress = $Settings.contactITEmailAddress } + if ($Settings.contactITNotes) { $Body.contactITNotes = $Settings.contactITNotes } + if ($Settings.onlineSupportSiteName) { $Body.onlineSupportSiteName = $Settings.onlineSupportSiteName } + if ($Settings.onlineSupportSiteUrl) { $Body.onlineSupportSiteUrl = $Settings.onlineSupportSiteUrl } + if ($Settings.privacyUrl) { $Body.privacyUrl = $Settings.privacyUrl } + + $cmdparams = @{ + tenantid = $tenant + uri = 'https://graph.microsoft.com/beta/deviceManagement/intuneBrandingProfiles/c3a59481-1bf2-46ce-94b3-66eec07a8d60/' + AsApp = $true + Type = 'PATCH' + Body = ($Body | ConvertTo-Json) + ContentType = 'application/json; charset=utf-8' + } + + try { + New-GraphPostRequest @cmdparams + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Successfully updated Intune Branding Profile' -sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to update Intune Branding Profile. Error: $ErrorMessage" -sev Error + } + } + } + + if ($Settings.alert -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Intune Branding Profile is correctly configured' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Intune Branding Profile is not correctly configured' -sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'intuneBrandingProfile' -FieldValue [bool]$StateIsCorrect -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 index 8f5a1dc0ef46..b150c84e2f0a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 @@ -4,6 +4,7 @@ function Invoke-CIPPStandardintuneDeviceRetirementDays { Internal #> param($Tenant, $Settings) + $CurrentInfo = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/deviceManagement/managedDeviceCleanupSettings' -tenantid $Tenant) $StateIsCorrect = if ($PreviousSetting.DeviceInactivityBeforeRetirementInDays -eq $Settings.days) { $true } else { $false } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 index cbe6519ce66f..95dfcec5a26d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 @@ -4,10 +4,18 @@ function Invoke-CIPPStandardsharingCapability { Internal #> param($Tenant, $Settings) + $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true - # $CurrentInfo.sharingCapability.GetType() - $Settings.Level - $CurrentInfo.sharingCapability + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'sharingCapability' -FieldValue $CurrentInfo.sharingCapability -StoreAs string -Tenant $tenant + } + + # Input validation + if (([string]::IsNullOrWhiteSpace($Settings.sharingCapability) -or $Settings.sharingCapability -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'sharingCapability: Invalid sharingCapability parameter set' -sev Error + Return + } If ($Settings.remediate -eq $true) { @@ -34,8 +42,4 @@ function Invoke-CIPPStandardsharingCapability { Write-LogMessage -API 'Standards' -tenant $tenant -message "Sharing level is not set to $($Settings.Level)" -sev Alert } } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'sharingCapability' -FieldValue $CurrentInfo.sharingCapability -StoreAs string -Tenant $tenant - } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingDomainRestriction.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingDomainRestriction.ps1 new file mode 100644 index 000000000000..9c7e7d11f555 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingDomainRestriction.ps1 @@ -0,0 +1,63 @@ +function Invoke-CIPPStandardsharingDomainRestriction { + <# + .FUNCTIONALITY + Internal + #> + + param($Tenant, $Settings) + $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true + + if ($Settings.Mode -eq 'none' -or $null -eq $Settings.Mode) { + $StateIsCorrect = $CurrentState.sharingDomainRestrictionMode -eq 'none' + } else { + $SelectedDomains = [String[]]$Settings.Domains.Split(',').Trim() + $StateIsCorrect = ($CurrentState.sharingDomainRestrictionMode -eq $Settings.Mode) -and + ($Settings.Mode -eq 'allowList' -and (!(Compare-Object -ReferenceObject $CurrentState.sharingAllowedDomainList -DifferenceObject $SelectedDomains))) -or + ($Settings.Mode -eq 'blockList' -and (!(Compare-Object -ReferenceObject $CurrentState.sharingBlockedDomainList -DifferenceObject $SelectedDomains))) + } + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Sharing Domain Restriction is already correctly configured' -sev Info + } else { + $Body = @{ + sharingDomainRestrictionMode = $Settings.Mode + } + + if ($Settings.Mode -eq 'AllowList') { + $Body.Add('sharingAllowedDomainList', $SelectedDomains) + } elseif ($Settings.Mode -eq 'BlockList') { + $Body.Add('sharingBlockedDomainList', $SelectedDomains) + } + + $cmdparams = @{ + tenantid = $tenant + uri = 'https://graph.microsoft.com/beta/admin/sharepoint/settings' + AsApp = $true + Type = 'PATCH' + Body = ($Body | ConvertTo-Json) + ContentType = 'application/json' + } + + try { + New-GraphPostRequest @cmdparams + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Successfully updated Sharing Domain Restriction settings' -sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to update Sharing Domain Restriction settings. Error: $ErrorMessage" -sev Error + } + } + } + + if ($Settings.alert -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Sharing Domain Restriction is correctly configured' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Sharing Domain Restriction is not correctly configured' -sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'sharingDomainRestriction' -FieldValue [bool]$StateIsCorrect -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Webhooks/Get-CIPPAuditLogContent.ps1 b/Modules/CIPPCore/Public/Webhooks/Get-CIPPAuditLogContent.ps1 new file mode 100644 index 000000000000..7a751bda4aef --- /dev/null +++ b/Modules/CIPPCore/Public/Webhooks/Get-CIPPAuditLogContent.ps1 @@ -0,0 +1,27 @@ +function Get-CIPPAuditLogContent { + <# + .SYNOPSIS + Get the content of an audit log. + .PARAMETER ContentUri + The URI of the content to get. + .PARAMETER TenantFilter + The tenant to filter on. + .EXAMPLE + Get-CIPPAuditLogContent -ContentUri 'https://manage.office.com/api/v1.0/contoso.com/activity/feed/subscriptions/content?contentType=Audit.General&PublisherIdentifier=00000000-0000-0000-0000-000000000000' -TenantFilter 'contoso.com' + .FUNCTIONALITY + Internal + #> + [CmdletBinding()] + Param( + [Parameter(ValueFromPipelineByPropertyName = $true, Mandatory = $true)] + [string[]]$ContentUri, + [Parameter(ValueFromPipelineByPropertyName = $true, Mandatory = $true)] + [string]$TenantFilter + ) + + Process { + foreach ($Uri in $ContentUri) { + New-GraphPOSTRequest -type GET -uri $Uri -tenantid $TenantFilter -scope 'https://manage.office.com/.default' + } + } +} \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Webhooks/Get-CIPPAuditLogContentBundles.ps1 b/Modules/CIPPCore/Public/Webhooks/Get-CIPPAuditLogContentBundles.ps1 new file mode 100644 index 000000000000..43fe9ac024c7 --- /dev/null +++ b/Modules/CIPPCore/Public/Webhooks/Get-CIPPAuditLogContentBundles.ps1 @@ -0,0 +1,87 @@ +function Get-CIPPAuditLogContentBundles { + <# + .SYNOPSIS + Get the available audit log bundles + .DESCRIPTION + Query the Office 365 Activity Log API for available content bundles. + .PARAMETER TenantFilter + The tenant to filter on. + .PARAMETER ContentType + The type of content to get. + .PARAMETER StartTime + The start time to filter on. + .PARAMETER EndTime + The end time to filter on. + .PARAMETER ShowAll + Show all content, default is only show new content + .EXAMPLE + Get-CIPPAuditLogContentBundles -TenantFilter 'contoso.com' -ContentType 'Audit.AzureActiveDirectory' + .FUNCTIONALITY + Internal + #> + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [string]$TenantFilter, + [Parameter(Mandatory = $true)] + [ValidateSet('Audit.AzureActiveDirectory', 'Audit.Exchange')] + [string]$ContentType, + [datetime]$StartTime, + [datetime]$EndTime, + [switch]$ShowAll + ) + + if ($TenantFilter -eq 'AllTenants') { + throw 'AllTenants is not a valid tenant filter for webhooks' + } + + if (!($TenantFilter -match '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$')) { + $DefaultDomainName = $TenantFilter + $TenantFilter = (Get-Tenants | Where-Object { $_.defaultDomainName -eq $TenantFilter }).customerId + } else { + $DefaultDomainName = (Get-Tenants | Where-Object { $_.customerId -eq $TenantFilter }).defaultDomainName + } + + $WebhookTable = Get-CippTable -tablename 'webhookTable' + $WebhookConfig = Get-CIPPAzDataTableEntity @WebhookTable -Filter "PartitionKey eq '$DefaultDomainName' and Version eq '3' and Resource eq '$ContentType'" + + if (!$WebhookConfig) { + throw "No webhook config found for $DefaultDomainName - $ContentType" + } + + $Parameters = @{ + 'contentType' = $ContentType + 'PublisherIdentifier' = $env:TenantId + } + + if (!$ShowAll.IsPresent) { + if (!$StartTime) { + $StartTime = (Get-Date).AddMinutes(-30) + $EndTime = Get-Date + } + } + + if ($StartTime) { + $Parameters.Add('startTime', $StartTime.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss')) + if ($EndTime) { + $Parameters.Add('endTime', $EndTime.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss')) + } else { + $Parameters.Add('endTime', ($StartTime).AddHours(24).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss')) + } + } + + Write-Information "StartTime: $StartTime" + Write-Information "EndTime: $EndTime" + $GraphQuery = [System.UriBuilder]('https://manage.office.com/api/v1.0/{0}/activity/feed/subscriptions/content' -f $TenantFilter) + $ParamCollection = [System.Web.HttpUtility]::ParseQueryString([String]::Empty) + foreach ($Item in ($Parameters.GetEnumerator())) { + $ParamCollection.Add($Item.Key, $Item.Value) + } + $GraphQuery.Query = $ParamCollection.ToString() + + Write-Verbose "GET [ $($GraphQuery.ToString()) ]" + $LogBundles = New-GraphGetRequest -uri $GraphQuery.ToString() -tenantid $TenantFilter -scope 'https://manage.office.com/.default' -IncludeResponseHeaders + $AuditLogContents = $LogBundles | Select-Object contentId, contentUri, contentCreated, contentExpiration, contentType, @{Name = 'TenantFilter'; Expression = { $TenantFilter } }, @{ Name = 'DefaultDomainName'; Expression = { $DefaultDomainName } } + + return $AuditLogContents +} \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Invoke-CIPPGraphWebhookProcessing.ps1 b/Modules/CIPPCore/Public/Webhooks/Invoke-CIPPGraphWebhookProcessing.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-CIPPGraphWebhookProcessing.ps1 rename to Modules/CIPPCore/Public/Webhooks/Invoke-CIPPGraphWebhookProcessing.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-CIPPGraphWebhookRenewal.ps1 b/Modules/CIPPCore/Public/Webhooks/Invoke-CIPPGraphWebhookRenewal.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-CIPPGraphWebhookRenewal.ps1 rename to Modules/CIPPCore/Public/Webhooks/Invoke-CIPPGraphWebhookRenewal.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-CIPPPartnerWebhookProcessing.ps1 b/Modules/CIPPCore/Public/Webhooks/Invoke-CIPPPartnerWebhookProcessing.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-CIPPPartnerWebhookProcessing.ps1 rename to Modules/CIPPCore/Public/Webhooks/Invoke-CIPPPartnerWebhookProcessing.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-CIPPWebhookProcessing.ps1 b/Modules/CIPPCore/Public/Webhooks/Invoke-CIPPWebhookProcessing.ps1 similarity index 97% rename from Modules/CIPPCore/Public/Invoke-CIPPWebhookProcessing.ps1 rename to Modules/CIPPCore/Public/Webhooks/Invoke-CIPPWebhookProcessing.ps1 index a1787ddbae34..d5db2cf47076 100644 --- a/Modules/CIPPCore/Public/Invoke-CIPPWebhookProcessing.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/Invoke-CIPPWebhookProcessing.ps1 @@ -43,7 +43,7 @@ function Invoke-CippWebhookProcessing { "No Inbox Rules found for $username. We have not disabled any rules." } "Completed BEC Remediate for $username" - Write-LogMessage -API 'BECRemediate' -tenant $tenantfilter -message "Executed Remediation for $username" -sev 'Info' + Write-LogMessage -API 'BECRemediate' -tenant $tenantfilter -message "Executed Remediation for $username" -sev 'Info' } 'cippcommand' { $CommandSplat = @{} @@ -85,7 +85,7 @@ function Invoke-CippWebhookProcessing { ActionsTaken = [string]($ActionResults | ConvertTo-Json -Depth 15 -Compress) } | ConvertTo-Json -Depth 15 -Compress Write-Host 'Sending Webhook Content' - + #Write-Host $JsonContent Send-CIPPAlert -Type 'webhook' -Title $GenerateJSON.Title -JSONContent $JsonContent -TenantFilter $TenantFilter } } diff --git a/Modules/CIPPCore/Public/Invoke-RemoveWebhookAlert.ps1 b/Modules/CIPPCore/Public/Webhooks/Invoke-RemoveWebhookAlert.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemoveWebhookAlert.ps1 rename to Modules/CIPPCore/Public/Webhooks/Invoke-RemoveWebhookAlert.ps1 diff --git a/Modules/CIPPCore/Public/New-CIPPGraphSubscription.ps1 b/Modules/CIPPCore/Public/Webhooks/New-CIPPGraphSubscription.ps1 similarity index 86% rename from Modules/CIPPCore/Public/New-CIPPGraphSubscription.ps1 rename to Modules/CIPPCore/Public/Webhooks/New-CIPPGraphSubscription.ps1 index 535156115d0b..eebd1163d61f 100644 --- a/Modules/CIPPCore/Public/New-CIPPGraphSubscription.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/New-CIPPGraphSubscription.ps1 @@ -21,42 +21,32 @@ function New-CIPPGraphSubscription { if ($auditLogAPI) { $CIPPID = (New-Guid).GUID $Resource = $EventType - $CIPPAuditURL = "$BaseURL/API/Publicwebhooks?EventType=$EventType&CIPPID=$CIPPID&version=2" - $AuditLogParams = @{ - webhook = @{ - 'address' = $CIPPAuditURL - } - } | ConvertTo-Json - #List existing webhook subscriptions in table - $WebhookFilter = "PartitionKey eq '$($TenantFilter)' and Resource eq '$Resource' and Version eq '2'" + $WebhookFilter = "PartitionKey eq '$($TenantFilter)' and Resource eq '$Resource' and Version eq '3'" $ExistingWebhooks = Get-CIPPAzDataTableEntity @WebhookTable -Filter $WebhookFilter $MatchedWebhook = $ExistingWebhooks try { if (!$MatchedWebhook) { $WebhookRow = @{ - PartitionKey = [string]$TenantFilter - RowKey = [string]$CIPPID - Resource = $Resource - Expiration = 'Does Not Expire' - WebhookNotificationUrl = [string]$CIPPAuditURL - Version = '2' + PartitionKey = [string]$TenantFilter + RowKey = [string]$CIPPID + Resource = [string]$Resource + Expiration = [string]'Does Not Expire' + Version = [string]'3' } Add-CIPPAzDataTableEntity @WebhookTable -Entity $WebhookRow Write-Host "Creating webhook subscription for $EventType" - $AuditLog = New-GraphPOSTRequest -uri "https://manage.office.com/api/v1.0/$($TenantFilter)/activity/feed/subscriptions/start?contentType=$EventType&PublisherIdentifier=$($TenantFilter)" -tenantid $TenantFilter -type POST -scope 'https://manage.office.com/.default' -body $AuditLogparams -verbose + $AuditLog = New-GraphPOSTRequest -type POST -uri "https://manage.office.com/api/v1.0/$($TenantFilter)/activity/feed/subscriptions/start?contentType=$EventType&PublisherIdentifier=$($env:TenantId)" -tenantid $TenantFilter -scope 'https://manage.office.com/.default' -body '{}' -verbose Write-LogMessage -user $ExecutingUser -API $APIName -message "Created Webhook subscription for $($TenantFilter) for the log $($EventType)" -Sev 'Info' -tenant $TenantFilter - } else { - Write-LogMessage -user $ExecutingUser -API $APIName -message "No webhook creation required for $($TenantFilter). Already exists" -Sev 'Info' -tenant $TenantFilter } - return @{ success = $true; message = "Created Webhook subscription for $($TenantFilter) for the log $($EventType)" } + return @{ Success = $true; message = "Created Webhook subscription for $($TenantFilter) for the log $($EventType)" } } catch { if ($_.Exception.Message -like '*already exists*') { return @{ success = $true; message = "Webhook exists for $($TenantFilter) for the log $($EventType)" } Write-LogMessage -user $ExecutingUser -API $APIName -message "Webhook subscription for $($TenantFilter) already exists" -Sev 'Info' -tenant $TenantFilter } else { Remove-AzDataTableEntity @WebhookTable -Entity @{ PartitionKey = $TenantFilter; RowKey = [string]$CIPPID } | Out-Null - Write-LogMessage -user $ExecutingUser -API $APIName -message "Failed to create Webhook Subscription for $($TenantFilter): $($_.Exception.Message)" -Sev 'Error' -tenant $TenantFilter + Write-LogMessage -user $ExecutingUser -API $APIName -message "Failed to create Webhook Subscription for $($TenantFilter): $($_.Exception.Message)" -Sev 'Error' -tenant $TenantFilter -LogData (Get-CippException -Exception $_) return @{ success = $false; message = "Failed to create Webhook Subscription for $($TenantFilter): $($_.Exception.Message)" } } } @@ -95,11 +85,9 @@ function New-CIPPGraphSubscription { if ($Existing.WebhookUrl) { $Action = 'Updated' $Method = 'PUT' - Write-Host 'updating webhook' } else { $Action = 'Created' $Method = 'POST' - Write-Host 'creating webhook' } $Uri = 'https://api.partnercenter.microsoft.com/webhooks/v1/registration' diff --git a/Modules/CIPPCore/Public/Remove-CIPPGraphSubscription.ps1 b/Modules/CIPPCore/Public/Webhooks/Remove-CIPPGraphSubscription.ps1 similarity index 99% rename from Modules/CIPPCore/Public/Remove-CIPPGraphSubscription.ps1 rename to Modules/CIPPCore/Public/Webhooks/Remove-CIPPGraphSubscription.ps1 index 88138b99ccc3..e64f366d7830 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPGraphSubscription.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/Remove-CIPPGraphSubscription.ps1 @@ -13,7 +13,7 @@ function Remove-CIPPGraphSubscription { if ($Cleanup) { #list all subscriptions on the management API $Subscriptions = New-GraphPOSTRequest -type GET -uri "https://manage.office.com/api/v1.0/$($TenantFilter)/activity/feed/subscriptions/list" -scope 'https://manage.office.com/.default' -tenantid $TenantFilter -verbose - foreach ($Sub in $Subscriptions | Where-Object { $_.webhook.address -like '*CIPP*' -and $_.webhook.address -notlike '*version=2*' }) { + foreach ($Sub in $Subscriptions | Where-Object { $_.webhook.address -like '*CIPP*' -and $_.webhook.address -notlike '*version=3*' }) { Try { $AuditLog = New-GraphPOSTRequest -uri "https://manage.office.com/api/v1.0/$($TenantFilter)/activity/feed/subscriptions/stop?contentType=$($sub.contentType)" -scope 'https://manage.office.com/.default' -tenantid $TenantFilter -type POST -body '{}' -verbose Try { diff --git a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 new file mode 100644 index 000000000000..dd3158876945 --- /dev/null +++ b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 @@ -0,0 +1,190 @@ +function Test-CIPPAuditLogRules { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $true)] + $TenantFilter, + [Parameter(Mandatory = $true)] + $ContentUri, + [Parameter(Mandatory = $true)] + [ValidateSet('Audit.AzureActiveDirectory', 'Audit.Exchange')] + $LogType + ) + + $Results = [PSCustomObject]@{ + TotalLogs = 0 + MatchedLogs = 0 + MatchedRules = @() + DataToProcess = @() + } + + $ExtendedPropertiesIgnoreList = @( + 'OAuth2:Authorize' + 'OAuth2:Token' + 'SAS:EndAuth' + 'SAS:ProcessAuth' + ) + + $TrustedIPTable = Get-CIPPTable -TableName 'trustedIps' + $ConfigTable = Get-CIPPTable -TableName 'WebhookRules' + $ConfigEntries = Get-CIPPAzDataTableEntity @ConfigTable + $Configuration = $ConfigEntries | Where-Object { ($_.Tenants -match $TenantFilter -or $_.Tenants -match 'AllTenants') } | ForEach-Object { + [pscustomobject]@{ + Tenants = ($_.Tenants | ConvertFrom-Json).fullValue + Conditions = $_.Conditions + Actions = $_.Actions + LogType = $_.Type + } + } + $AuditLogQuery = @{ + TenantFilter = $TenantFilter + ContentUri = $ContentUri + } + Write-Information 'Getting data from Office 365 Management Activity API' + $Data = Get-CIPPAuditLogContent @AuditLogQuery + $LogCount = ($Data | Measure-Object).Count + Write-Information "Logs to process: $LogCount" + $Results.TotalLogs = $LogCount + if ($LogCount -gt 0) { + $PreProccessedData = $Data | Select-Object *, CIPPAction, CIPPClause, CIPPGeoLocation, CIPPBadRepIP, CIPPHostedIP, CIPPIPDetected, CIPPLocationInfo, CIPPExtendedProperties, CIPPDeviceProperties, CIPPParameters, CIPPModifiedProperties -ErrorAction SilentlyContinue + $LocationTable = Get-CIPPTable -TableName 'knownlocationdb' + $ProcessedData = foreach ($Data in $PreProccessedData) { + try { + if ($Data.ExtendedProperties) { + $Data.CIPPExtendedProperties = ($Data.ExtendedProperties | ConvertTo-Json) + if ($Data.CIPPExtendedProperties.RequestType -in $ExtendedPropertiesIgnoreList) { + Write-Information 'No need to process this operation as its in our ignore list' + continue + } + $Data.ExtendedProperties | ForEach-Object { $Data | Add-Member -NotePropertyName $_.Name -NotePropertyValue $_.Value -Force -ErrorAction SilentlyContinue } + } + if ($Data.DeviceProperties) { + $Data.CIPPDeviceProperties = ($Data.DeviceProperties | ConvertTo-Json) + $Data.DeviceProperties | ForEach-Object { $Data | Add-Member -NotePropertyName $_.Name -NotePropertyValue $_.Value -Force -ErrorAction SilentlyContinue } + } + if ($Data.parameters) { + $Data.CIPPParameters = ($Data.parameters | ConvertTo-Json) + $Data.parameters | ForEach-Object { $Data | Add-Member -NotePropertyName $_.Name -NotePropertyValue $_.Value -Force -ErrorAction SilentlyContinue } + } + if ($Data.ModifiedProperties) { + $Data.CIPPModifiedProperties = ($Data.ModifiedProperties | ConvertTo-Json) + try { + $Data.ModifiedProperties | ForEach-Object { $Data | Add-Member -NotePropertyName "$($_.Name)" -NotePropertyValue "$($_.NewValue)" -Force -ErrorAction SilentlyContinue } + } catch { + #Write-Information ($Data.ModifiedProperties | ConvertTo-Json -Depth 10) + } + try { + $Data.ModifiedProperties | ForEach-Object { $Data | Add-Member -NotePropertyName $("Previous_Value_$($_.Name)") -NotePropertyValue "$($_.OldValue)" -Force -ErrorAction SilentlyContinue } + } catch { + #Write-Information ($Data.ModifiedProperties | ConvertTo-Json -Depth 10) + } + } + + if ($Data.clientip) { + if ($Data.clientip -match '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+$') { + $Data.clientip = $Data.clientip -replace ':\d+$', '' # Remove the port number if present + } + # Check if IP is on trusted IP list + $TrustedIP = Get-CIPPAzDataTableEntity @TrustedIPTable -Filter "PartitionKey eq '$TenantFilter' and RowKey eq '$($Data.clientip)' and state eq 'Trusted'" + if ($TrustedIP) { + Write-Information "IP $($Data.clientip) is trusted" + continue + } + + $Location = Get-CIPPAzDataTableEntity @LocationTable -Filter "RowKey eq '$($Data.clientIp)'" | Select-Object -Last 1 + if ($Location) { + $Country = $Location.CountryOrRegion + $City = $Location.City + $Proxy = $Location.Proxy + $hosting = $Location.Hosting + $ASName = $Location.ASName + } else { + try { + $Location = Get-CIPPGeoIPLocation -IP $Data.clientip + } catch { + Write-Information "Unable to get IP location for $($Data.clientip): $($_.Exception.Messge)" + } + $Country = if ($Location.CountryCode) { $Location.CountryCode } else { 'Unknown' } + $City = if ($Location.City) { $Location.City } else { 'Unknown' } + $Proxy = if ($Location.Proxy -ne $null) { $Location.Proxy } else { 'Unknown' } + $hosting = if ($Location.Hosting -ne $null) { $Location.Hosting } else { 'Unknown' } + $ASName = if ($Location.ASName) { $Location.ASName } else { 'Unknown' } + $IP = $Data.ClientIP + $LocationInfo = @{ + RowKey = [string]$Data.clientip + PartitionKey = [string]$Data.id + Tenant = [string]$TenantFilter + CountryOrRegion = "$Country" + City = "$City" + Proxy = "$Proxy" + Hosting = "$hosting" + ASName = "$ASName" + } + try { + $null = Add-CIPPAzDataTableEntity @LocationTable -Entity $LocationInfo -Force + } catch { + Write-Information "Failed to add location info for $($Data.clientip) to cache: $($_.Exception.Message)" + + } + } + $Data.CIPPGeoLocation = $Country + $Data.CIPPBadRepIP = $Proxy + $Data.CIPPHostedIP = $hosting + $Data.CIPPIPDetected = $IP + $Data.CIPPLocationInfo = ($Location | ConvertTo-Json) + } + $Data | Select-Object * -ExcludeProperty ExtendedProperties, DeviceProperties, parameters + } catch { + Write-Information "Audit log: Error processing data: $($_.Exception.Message)`r`n$($_.InvocationInfo.PositionMessage)" + Write-LogMessage -API 'Webhooks' -message 'Error Processing Audit Log Data' -LogData (Get-CippException -Exception $_) -sev Error -tenant $TenantFilter + } + } + + #Filter data based on conditions. + $Where = $Configuration | Where-Object { $_.LogType -eq $LogType } | ForEach-Object { + $conditions = $_.Conditions | ConvertFrom-Json | Where-Object { $_.Input.value -ne '' } + $actions = $_.Actions + $conditionStrings = [System.Collections.Generic.List[string]]::new() + $CIPPClause = [System.Collections.Generic.List[string]]::new() + foreach ($condition in $conditions) { + $value = if ($condition.Input.value -is [array]) { + $arrayAsString = $condition.Input.value | ForEach-Object { + "'$_'" + } + "@($($arrayAsString -join ', '))" + } else { "'$($condition.Input.value)'" } + + $conditionStrings.Add("`$(`$_.$($condition.Property.label)) -$($condition.Operator.value) $value") + $CIPPClause.Add("$($condition.Property.label) is $($condition.Operator.label) $value") + } + $finalCondition = $conditionStrings -join ' -AND ' + + [PSCustomObject]@{ + clause = $finalCondition + expectedAction = $actions + CIPPClause = $CIPPClause + } + + } + Write-Information "Webhook: The list of operations in the data are $(($ProcessedData.operation | Select-Object -Unique) -join ', ')" + + $MatchedRules = [System.Collections.Generic.List[string]]::new() + $DataToProcess = foreach ($clause in $Where) { + Write-Information "Webhook: Processing clause: $($clause.clause)" + Write-Information "Webhook: If this clause would be true, the action would be: $($clause.expectedAction)" + $ReturnedData = $ProcessedData | Where-Object { Invoke-Expression $clause.clause } + if ($ReturnedData) { + $ReturnedData = foreach ($item in $ReturnedData) { + $item.CIPPAction = $clause.expectedAction + $item.CIPPClause = $clause.CIPPClause -join ' and ' + $MatchedRules.Add($clause.CIPPClause -join ' and ') + $item + } + } + $ReturnedData + } + $Results.MatchedRules = $MatchedRules | Select-Object -Unique + $Results.MatchedLogs = ($DataToProcess | Measure-Object).Count + $Results.DataToProcess = $DataToProcess + } + $Results +} \ No newline at end of file diff --git a/Scheduler_PollAuditLogs/function.json b/Scheduler_PollAuditLogs/function.json new file mode 100644 index 000000000000..f30537d11b34 --- /dev/null +++ b/Scheduler_PollAuditLogs/function.json @@ -0,0 +1,15 @@ +{ + "bindings": [ + { + "name": "Timer", + "schedule": "0 */15 * * * *", + "direction": "in", + "type": "timerTrigger" + }, + { + "name": "starter", + "type": "durableClient", + "direction": "in" + } + ] +} diff --git a/Scheduler_PollAuditLogs/run.ps1 b/Scheduler_PollAuditLogs/run.ps1 new file mode 100644 index 000000000000..828cf3327c5e --- /dev/null +++ b/Scheduler_PollAuditLogs/run.ps1 @@ -0,0 +1,34 @@ +param($Timer) + +try { + $webhookTable = Get-CIPPTable -tablename webhookTable + $Webhooks = Get-CIPPAzDataTableEntity @webhookTable -Filter "Version eq '3'" | Where-Object { $_.Resource -match '^Audit' } + if (($Webhooks | Measure-Object).Count -eq 0) { + Write-Host 'No webhook subscriptions found. Exiting.' + return + } + + <#try { + $RunningQueue = Invoke-ListCippQueue | Where-Object { $_.Reference -eq 'AuditLogCollection' -and $_.Status -ne 'Completed' -and $_.Status -ne 'Failed' -and $_.Timestamp.DateTime.ToLocalTime() -lt (Get-Date).AddMinutes(-10) } + if ($RunningQueue) { + Write-Host 'Audit log collection already running' + return + } + } catch {}#> + + $StartTime = (Get-Date).AddMinutes(-30) + $EndTime = Get-Date + + $Queue = New-CippQueueEntry -Name 'Audit Log Collection' -Reference 'AuditLogCollection' -TotalTasks ($Webhooks | Sort-Object -Property PartitionKey -Unique | Measure-Object).Count + $Batch = $Webhooks | Sort-Object -Property PartitionKey -Unique | Select-Object @{Name = 'TenantFilter'; Expression = { $_.PartitionKey } }, @{Name = 'QueueId'; Expression = { $Queue.RowKey } }, @{Name = 'FunctionName'; Expression = { 'AuditLogTenant' } }, @{Name = 'StartTime'; Expression = { $StartTime } }, @{Name = 'EndTime'; Expression = { $EndTime } } + $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'" +} catch { + Write-LogMessage -API 'Webhooks' -message 'Error processing webhooks' -sev Error -LogData (Get-CippException -Exception $_) + Write-Host ( 'Webhook error {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message) +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000000..9c41ecf7e309 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "CIPP-API", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/version_latest.txt b/version_latest.txt index a94a88fbb889..cf5136119071 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -5.8.5 \ No newline at end of file +5.9.0 \ No newline at end of file