diff --git a/CIPP-Permissions.json b/CIPP-Permissions.json index 96368090acd7..95c4e7dea816 100644 --- a/CIPP-Permissions.json +++ b/CIPP-Permissions.json @@ -225,6 +225,11 @@ "Name": "Organization.ReadWrite.All", "Description": "Allows the app to read and write the organization and related resources, on your behalf. Related resources include things like subscribed skus and tenant branding information." }, + { + "Id": "346c19ff-3fb2-4e81-87a0-bac9e33990c1", + "Name": "OrgSettings-Forms.ReadWrite.All", + "Description": "Allows the app to read and write organization-wide Microsoft Forms settings on your behalf." + }, { "Id": "e67e6727-c080-415e-b521-e3f35d5248e9", "Name": "PeopleSettings.ReadWrite.All", @@ -577,6 +582,11 @@ "Name": "Organization.ReadWrite.All", "Description": "Allows the app to read and write the organization and related resources, without a signed-in user. Related resources include things like subscribed skus and tenant branding information." }, + { + "Id": "2cb92fee-97a3-4034-8702-24a6f5d0d1e9", + "Name": "OrgSettings-Forms.ReadWrite.All", + "Description": "Allows the app to read and write organization-wide Microsoft Forms settings, without a signed-in user." + }, { "Id": "b6890674-9dd5-4e42-bb15-5af07f541ae1", "Name": "PeopleSettings.ReadWrite.All", @@ -637,6 +647,11 @@ "Name": "ReportSettings.ReadWrite.All", "Description": "Allows the app to read and update all admin report settings, such as whether to display concealed information in reports, without a signed-in user." }, + { + "Id": "025d3225-3f02-4882-b4c0-cd5b541a4e80", + "Name": "RoleManagement.ReadWrite.Exchange", + "Description": "Allows the app to read and manage the role-based access control (RBAC) settings for your organization's Exchange Online service, without a signed-in user. This includes reading, creating, updating, and deleting Exchange management role definitions, role groups, role group membership, role assignments, management scopes, and role assignment policies." + }, { "Id": "04c55753-2244-4c25-87fc-704ab82a4f69", "Name": "SecurityAnalyzedMessage.ReadWrite.All", diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertHuntressRogueApps.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertHuntressRogueApps.ps1 index a949986da6a3..8531738f452b 100644 --- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertHuntressRogueApps.ps1 +++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertHuntressRogueApps.ps1 @@ -13,7 +13,7 @@ function Get-CIPPAlertHuntressRogueApps { Param ( [Parameter(Mandatory = $false)] [Alias('input')] - [bool]$InputValue = $false, + $InputValue, $TenantFilter ) @@ -22,7 +22,7 @@ function Get-CIPPAlertHuntressRogueApps { $RogueAppFilter = $RogueApps.appId -join "','" $ServicePrincipals = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$filter=appId in ('$RogueAppFilter')" -tenantid $TenantFilter # If IgnoreDisabledApps is true, filter out disabled service principals - if ($InputValue) { + if ($InputValue -eq $true) { $ServicePrincipals = $ServicePrincipals | Where-Object { $_.accountEnabled -eq $true } } diff --git a/Modules/CIPPCore/Public/AuditLogs/New-CippAuditLogSearch.ps1 b/Modules/CIPPCore/Public/AuditLogs/New-CippAuditLogSearch.ps1 index 2bb80d31427f..a840dac13486 100644 --- a/Modules/CIPPCore/Public/AuditLogs/New-CippAuditLogSearch.ps1 +++ b/Modules/CIPPCore/Public/AuditLogs/New-CippAuditLogSearch.ps1 @@ -147,7 +147,7 @@ function New-CippAuditLogSearch { if ($IPAddressFilters) { $SearchParams.ipAddressFilters = @($IPAddressFilters) } - if ($ObjectIdFilterss) { + if ($ObjectIdFilters) { $SearchParams.objectIdFilters = @($ObjectIdFilters) } if ($AdministrativeUnitFilters) { 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 168342bd7701..08cf028b8704 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 @@ -83,7 +83,7 @@ function Push-DomainAnalyserDomain { # Setup Score Explanation $ScoreExplanation = [System.Collections.Generic.List[string]]::new() - # Check MX Record + #Region MX Check $MXRecord = Read-MXRecord -Domain $Domain -ErrorAction Stop $Result.ExpectedSPFRecord = $MXRecord.ExpectedInclude @@ -106,8 +106,9 @@ function Push-DomainAnalyserDomain { } else { $Result.MailProvider = $MXRecord.MailProvider.Name } + #EndRegion MX Check - # Get SPF Record + #Region SPF Check try { $SPFRecord = Read-SpfRecord -Domain $Domain -ErrorAction Stop if ($SPFRecord.RecordCount -gt 0) { @@ -126,12 +127,11 @@ function Push-DomainAnalyserDomain { Write-LogMessage -API 'DomainAnalyser' -tenant $DomainObject.TenantId -message $Message -LogData (Get-CippException -Exception $_) -sev Error } - # Check SPF Record - $Result.SPFPassAll = $false # Check warning + fail counts to ensure all tests pass #$SPFWarnCount = $SPFRecord.ValidationWarns | Measure-Object | Select-Object -ExpandProperty Count $SPFFailCount = $SPFRecord.ValidationFails | Measure-Object | Select-Object -ExpandProperty Count + $Result.SPFPassAll = $false if ($SPFFailCount -eq 0) { $ScoreDomain += $Scores.SPFCorrectAll @@ -139,8 +139,9 @@ function Push-DomainAnalyserDomain { } else { $ScoreExplanation.Add('SPF record did not pass validation') | Out-Null } + #EndRegion SPF Check - # Get DMARC Record + #Region DMARC Check try { $DMARCPolicy = Read-DmarcPolicy -Domain $Domain -ErrorAction Stop @@ -188,8 +189,9 @@ function Push-DomainAnalyserDomain { Write-LogMessage -API 'DomainAnalyser' -tenant $DomainObject.TenantId -message $Message -LogData (Get-CippException -Exception $_) -sev Error #return $Message } + #EndRegion DMARC Check - # DNS Sec Check + #Region DNS Sec Check try { $DNSSECResult = Test-DNSSEC -Domain $Domain -ErrorAction Stop $DNSSECFailCount = $DNSSECResult.ValidationFails | Measure-Object | Select-Object -ExpandProperty Count @@ -206,8 +208,9 @@ function Push-DomainAnalyserDomain { Write-LogMessage -API 'DomainAnalyser' -tenant $DomainObject.TenantId -message $Message -LogData (Get-CippException -Exception $_) -sev Error #return $Message } + #EndRegion DNS Sec Check - # DKIM Check + #Region DKIM Check try { $DkimParams = @{ Domain = $Domain @@ -241,7 +244,9 @@ function Push-DomainAnalyserDomain { Write-LogMessage -API 'DomainAnalyser' -tenant $DomainObject.TenantId -message $Message -LogData (Get-CippException -Exception $_) -sev Error #return $Message } + #EndRegion DKIM Check + #Region MSCNAME DKIM Records # Get Microsoft DKIM CNAME selector Records # Ugly, but i needed to create a scope/loop i could break out of without breaking the rest of the function foreach ($d in $Domain) { @@ -250,7 +255,7 @@ function Push-DomainAnalyserDomain { if ($Result.DKIMEnabled -eq $true) { continue } - # Test if its a onmicrosft.com domain, skip domain if it is + # Test if its a onmicrosoft.com domain, skip domain if it is if ($Domain -match 'onmicrosoft.com') { continue } @@ -264,28 +269,21 @@ function Push-DomainAnalyserDomain { } } + # Get the DKIM record from EXO. This is the only way to get the correct values for the MSCNAME records since the new format was introduced in May 2025. + $DKIM = (New-ExoRequest -tenantid $Tenant.Tenant -cmdlet 'Get-DkimSigningConfig' -Select 'Domain,Selector1CNAME,Selector2CNAME') | Where-Object { $_.Domain -eq $Domain } - # Compute the DKIM CNAME records from $Tenant.InitialDomainName according to this logic: https://learn.microsoft.com/en-us/defender-office-365/email-authentication-dkim-configure#syntax-for-dkim-cname-records - # Test if it has a - in the domain name - if ($Domain -like '*-*') { - Write-Information 'Domain has a - in it. Got to query EXO for the right values' - $DKIM = (New-ExoRequest -tenantid $Tenant.Tenant -cmdlet 'Get-DkimSigningConfig') | Where-Object { $_.Domain -eq $Domain } | Select-Object Domain, Selector1CNAME, Selector2CNAME - - # If no DKIM signing record is found, create a new disabled one - if ($null -eq $DKIM) { - Write-Information 'No DKIM record found in EXO - Creating new signing' - $NewDKIMSigningRequest = New-ExoRequest -tenantid $Tenant.Tenant -cmdlet 'New-DkimSigningConfig' -cmdParams @{ KeySize = 2048; DomainName = $Domain; Enabled = $false } - $Selector1Value = $NewDKIMSigningRequest.Selector1CNAME - $Selector2Value = $NewDKIMSigningRequest.Selector2CNAME - } else { - $Selector1Value = $DKIM.Selector1CNAME - $Selector2Value = $DKIM.Selector2CNAME - } + # If no DKIM signing record is found, create a new disabled one + if ($null -eq $DKIM) { + Write-Information 'No DKIM record found in EXO - Creating new signing' + $NewDKIMSigningRequest = New-ExoRequest -tenantid $Tenant.Tenant -cmdlet 'New-DkimSigningConfig' -cmdParams @{ KeySize = 2048; DomainName = $Domain; Enabled = $false } + $Selector1Value = $NewDKIMSigningRequest.Selector1CNAME + $Selector2Value = $NewDKIMSigningRequest.Selector2CNAME } else { - $Selector1Value = "selector1-$($Domain -replace '\.', '-' )._domainkey.$($Tenant.InitialDomainName)" - $Selector2Value = "selector2-$($Domain -replace '\.', '-' )._domainkey.$($Tenant.InitialDomainName)" + $Selector1Value = $DKIM.Selector1CNAME + $Selector2Value = $DKIM.Selector2CNAME } + # Create the MSCNAME object $MSCNAMERecords = [PSCustomObject]@{ Domain = $Domain @@ -304,7 +302,7 @@ function Push-DomainAnalyserDomain { Write-LogMessage -API 'DomainAnalyser' -tenant $DomainObject.TenantId -message "MS CNAME DKIM error: $($ErrorMessage.NormalizedError)" -LogData $ErrorMessage -sev Error } } - + #EndRegion MSCNAME DKIM Records # Final Score $Result.Score = $ScoreDomain $Result.ScorePercentage = [int](($Result.Score / $Result.MaximumScore) * 100) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ListScheduledItems.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ListScheduledItems.ps1 index ceadb14858a8..4361e6d64ee6 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ListScheduledItems.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ListScheduledItems.ps1 @@ -14,23 +14,29 @@ function Invoke-ListScheduledItems { $Headers = $Request.Headers Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - - # Interact with query parameters or the body of the request. - $ShowHidden = $Request.Query.ShowHidden ?? $Request.Body.ShowHidden - $Name = $Request.Query.Name ?? $Request.Body.Name - $Type = $Request.Query.Type ?? $Request.Body.Type - $ScheduledItemFilter = [System.Collections.Generic.List[string]]::new() $ScheduledItemFilter.Add("PartitionKey eq 'ScheduledTask'") - if ($ShowHidden -eq $true) { - $ScheduledItemFilter.Add('Hidden eq true') + $Id = $Request.Query.Id ?? $Request.Body.Id + if ($Id) { + # Interact with query parameters. + $ScheduledItemFilter.Add("RowKey eq '$($Id)'") } else { - $ScheduledItemFilter.Add('Hidden eq false') - } + # Interact with query parameters or the body of the request. + $ShowHidden = $Request.Query.ShowHidden ?? $Request.Body.ShowHidden + $Name = $Request.Query.Name ?? $Request.Body.Name + $Type = $Request.Query.Type ?? $Request.Body.Type + + if ($ShowHidden -eq $true) { + $ScheduledItemFilter.Add('Hidden eq true') + } else { + $ScheduledItemFilter.Add('Hidden eq false') + } + + if ($Name) { + $ScheduledItemFilter.Add("Name eq '$($Name)'") + } - if ($Name) { - $ScheduledItemFilter.Add("Name eq '$($Name)'") } $Filter = $ScheduledItemFilter -join ' and ' @@ -42,7 +48,7 @@ function Invoke-ListScheduledItems { } else { $HiddenTasks = $true } - $Tasks = Get-CIPPAzDataTableEntity @Table -Filter $Filter | Where-Object { $_.Hidden -ne $HiddenTasks } + $Tasks = Get-CIPPAzDataTableEntity @Table -Filter $Filter if ($Type) { $Tasks = $Tasks | Where-Object { $_.command -eq $Type } } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-AddSharedMailbox.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-AddSharedMailbox.ps1 index 797025084402..4ad094971c5d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-AddSharedMailbox.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-AddSharedMailbox.ps1 @@ -29,7 +29,7 @@ Function Invoke-AddSharedMailbox { Shared = $true } $AddSharedRequest = New-ExoRequest -tenantid $Tenant -cmdlet 'New-Mailbox' -cmdParams $BodyToShip - $Body = $Results.Add("Successfully created shared mailbox: $Email.") + $Body = $Results.Add("Successfully created shared mailbox: $Email") Write-LogMessage -Headers $Headers -API $APIName -tenant $Tenant -message "Created shared mailbox $($MailboxObject.displayName) with email $Email" -Sev 'Info' # Block sign-in for the mailbox @@ -38,7 +38,7 @@ Function Invoke-AddSharedMailbox { $Body = $Results.Add("Blocked sign-in for shared mailbox $Email") } catch { $ErrorMessage = Get-CippException -Exception $_ - $Message = "Failed to block sign-in for shared mailbox $Email. Error: $($ErrorMessage.NormalizedError)" + $Message = "Failed to block sign-in for shared mailbox $Email Error: $($ErrorMessage.NormalizedError)" Write-LogMessage -Headers $Headers -API $APIName -tenant $Tenant -message $Message -Sev 'Error' -LogData $ErrorMessage $Body = $Results.Add($Message) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecSetOoO.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecSetOoO.ps1 index 1bd62dac8eb9..c262bfb5ce5d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecSetOoO.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecSetOoO.ps1 @@ -30,8 +30,8 @@ Function Invoke-ExecSetOoO { # User action uses input, edit exchange uses InternalMessage and ExternalMessage # User action disable OoO doesn't send any input if ($Request.Body.input) { - $InternalMessage = $Request.Body.input - $ExternalMessage = $Request.Body.input + $SplatParams.InternalMessage = $Request.Body.input + $SplatParams.ExternalMessage = $Request.Body.input } else { $InternalMessage = $Request.Body.InternalMessage $ExternalMessage = $Request.Body.ExternalMessage 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 86f1abdd4922..34ec25c7abdc 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 @@ -55,7 +55,7 @@ function Invoke-EditGroup { Write-Host "body: $($PatchObj | ConvertTo-Json -Depth 10 -Compress)" -ForegroundColor Yellow if ($UserObj.membershipRules) { $PatchObj | Add-Member -MemberType NoteProperty -Name 'membershipRule' -Value $UserObj.membershipRules -Force } try { - $patch = New-GraphPOSTRequest -type PATCH -uri "https://graph.microsoft.com/beta/groups/$($GroupId)" -tenantid $UserObj.tenantFilter -body ($PatchObj | ConvertTo-Json -Depth 10 -Compress) + $null = New-GraphPOSTRequest -type PATCH -uri "https://graph.microsoft.com/beta/groups/$($GroupId)" -tenantid $UserObj.tenantFilter -body ($PatchObj | ConvertTo-Json -Depth 10 -Compress) $Results.Add("Success - Edited group properties for $($GroupName) group. It might take some time to reflect the changes.") Write-LogMessage -headers $Headers -API $APIName -tenant $UserObj.tenantFilter -message "Edited group properties for $($GroupName) group" -Sev 'Info' } catch { @@ -134,7 +134,7 @@ function Invoke-EditGroup { }) } else { Write-LogMessage -API $APIName -tenant $TenantId -headers $Headers -message 'You cannot add a Contact to a Security Group or a M365 Group' -Sev 'Error' - $null = $Results.Add('Error - You cannot add a contact to a Security Group or a M365 Group') + $Results.Add('Error - You cannot add a contact to a Security Group or a M365 Group') } } catch { Write-Warning "Error in AddContacts: $($_.Exception.Message)" @@ -162,7 +162,7 @@ function Invoke-EditGroup { }) } else { Write-LogMessage -API $APIName-tenant $TenantId -headers $Headers -message 'You cannot remove a contact from a Security Group' -Sev 'Error' - $null = $Results.Add('You cannot remove a contact from a Security Group') + $Results.Add('You cannot remove a contact from a Security Group') } } } @@ -260,7 +260,7 @@ function Invoke-EditGroup { if ($GroupType -in @( 'Distribution List', 'Mail-Enabled Security') -and ($AddOwners -or $RemoveOwners)) { $CurrentOwners = New-ExoRequest -tenantid $TenantId -cmdlet 'Get-DistributionGroup' -cmdParams @{ Identity = $GroupId } -UseSystemMailbox $true | Select-Object -ExpandProperty ManagedBy - $NewManagedBy = [system.collections.generic.list[string]]::new() + $NewManagedBy = [System.Collections.Generic.List[string]]::new() foreach ($CurrentOwner in $CurrentOwners) { if ($RemoveOwners -and $RemoveOwners.addedFields.id -contains $CurrentOwner) { $OwnerToRemove = $RemoveOwners | Where-Object { $_.addedFields.id -eq $CurrentOwner } @@ -330,7 +330,7 @@ function Invoke-EditGroup { foreach ($ExoError in $LastError.error) { $Sev = 'Error' $Results.Add("Error - $ExoError") - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message $Message -Sev $Sev + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message $ExoError -Sev $Sev } foreach ($ExoLog in $ExoLogs) { @@ -344,39 +344,65 @@ function Invoke-EditGroup { } } - if ($UserObj.allowExternal -eq $true -and $GroupType -ne 'Security') { + # Only process allowExternal if it was explicitly sent + if ($null -ne $UserObj.allowExternal -and $GroupType -ne 'Security') { try { - Set-CIPPGroupAuthentication -ID $UserObj.mail -OnlyAllowInternal (!$UserObj.allowExternal) -GroupType $GroupType -tenantFilter $TenantId -APIName $APIName -Headers $Headers - $body = $Results.Add("Allowed external senders to send to $($UserObj.mail).") + $OnlyAllowInternal = $UserObj.allowExternal -eq $true ? $false : $true + Set-CIPPGroupAuthentication -ID $UserObj.mail -OnlyAllowInternal $OnlyAllowInternal -GroupType $GroupType -tenantFilter $TenantId -APIName $APIName -Headers $Headers + if ($UserObj.allowExternal -eq $true) { + $Results.Add("Allowed external senders to send to $($UserObj.mail).") + } else { + $Results.Add("Blocked external senders from sending to $($UserObj.mail).") + } } catch { - $body = $Results.Add("Failed to allow external senders to send to $($UserObj.mail).") - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Failed to allow external senders for $($UserObj.mail). Error:$($_.Exception.Message)" -Sev 'Error' + $action = if ($UserObj.allowExternal -eq $true) { 'allow' } else { 'block' } + $Results.Add("Failed to $action external senders for $($UserObj.mail).") } - } - if ($UserObj.sendCopies -eq $true) { + # Only process sendCopies if it was explicitly sent + if ($null -ne $UserObj.sendCopies) { try { - $Params = @{ Identity = $GroupId; subscriptionEnabled = $true; AutoSubscribeNewMembers = $true } - New-ExoRequest -tenantid $TenantId -cmdlet 'Set-UnifiedGroup' -cmdParams $Params -useSystemMailbox $true - - $MemberParams = @{ Identity = $GroupId; LinkType = 'members' } - $Members = New-ExoRequest -tenantid $TenantId -cmdlet 'Get-UnifiedGroupLinks' -cmdParams $MemberParams + if ($UserObj.sendCopies -eq $true) { + $Params = @{ Identity = $GroupId; subscriptionEnabled = $true; AutoSubscribeNewMembers = $true } + New-ExoRequest -tenantid $TenantId -cmdlet 'Set-UnifiedGroup' -cmdParams $Params -useSystemMailbox $true + + $MemberParams = @{ Identity = $GroupId; LinkType = 'members' } + $Members = New-ExoRequest -tenantid $TenantId -cmdlet 'Get-UnifiedGroupLinks' -cmdParams $MemberParams + + $MembershipIds = $Members | ForEach-Object { $_.ExternalDirectoryObjectId } + if ($MembershipIds) { + $subscriberParams = @{ Identity = $GroupId; LinkType = 'subscribers'; Links = @($MembershipIds | Where-Object { $_ }) } + + try { + New-ExoRequest -tenantid $TenantId -cmdlet 'Add-UnifiedGroupLinks' -cmdParams $subscriberParams -Anchor $UserObj.mail + } catch { + $ErrorMessage = Get-CippException -Exception $_ + Write-Warning "Error in SendCopies: Add-UnifiedGroupLinks $($ErrorMessage.NormalizedError) - $($_.InvocationInfo.ScriptLineNumber)" + throw "Error in SendCopies: Add-UnifiedGroupLinks $($ErrorMessage.NormalizedError)" + } - $MemberSmtpAddresses = $Members | ForEach-Object { $_.PrimarySmtpAddress } + } - if ($MemberSmtpAddresses) { - $subscriberParams = @{ Identity = $GroupId; LinkType = 'subscribers'; Links = @($MemberSmtpAddresses | Where-Object { $_ }) } - New-ExoRequest -tenantid $TenantId -cmdlet 'Add-UnifiedGroupLinks' -cmdParams $subscriberParams -Anchor $UserObj.mail + $Results.Add("Send Copies of team emails and events to team members inboxes for $($UserObj.mail) enabled.") + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Send Copies of team emails and events to team members inboxes for $($UserObj.mail) enabled." -Sev 'Info' + } else { + # Disable send copies. Has to be done in 2 calls, otherwise it fails saying AutoSubscribeNewMembers cannot be true when subscriptionEnabled is false. + # Why this happens and can't be done in one call, only Bill Gates and the mystical gods of Exchange knows. + $Params = @{ Identity = $GroupId; AutoSubscribeNewMembers = $false } + $null = New-ExoRequest -tenantid $TenantId -cmdlet 'Set-UnifiedGroup' -cmdParams $Params -useSystemMailbox $true + $Params = @{ Identity = $GroupId; subscriptionEnabled = $false } + $null = New-ExoRequest -tenantid $TenantId -cmdlet 'Set-UnifiedGroup' -cmdParams $Params -useSystemMailbox $true + + $Results.Add("Send Copies of team emails and events to team members inboxes for $($UserObj.mail) disabled.") + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Send Copies of team emails and events to team members inboxes for $($UserObj.mail) disabled." -Sev 'Info' } - - $body = $Results.Add("Send Copies of team emails and events to team members inboxes for $($UserObj.mail) enabled.") - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Send Copies of team emails and events to team members inboxes for $($UserObj.mail) enabled." -Sev 'Info' } catch { - Write-Warning "Error in SendCopies: $($_.Exception.Message) - $($_.InvocationInfo.ScriptLineNumber)" - Write-Warning ($_.InvocationInfo.PositionMessage) - $body = $Results.Add("Failed to Send Copies of team emails and events to team members inboxes for $($UserObj.mail).") - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Failed to Send Copies of team emails and events to team members inboxes for $($UserObj.mail). Error:$($_.Exception.Message)" -Sev 'Error' + $ErrorMessage = Get-CippException -Exception $_ + Write-Warning "Error in SendCopies: $($ErrorMessage.NormalizedError) - $($_.InvocationInfo.ScriptLineNumber)" + $action = if ($UserObj.sendCopies -eq $true) { 'enable' } else { 'disable' } + $Results.Add("Failed to $action Send Copies of team emails and events to team members inboxes for $($UserObj.mail).") + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Failed to $action Send Copies of team emails and events to team members inboxes for $($UserObj.mail). Error:$($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage } } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroups.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroups.ps1 index 6b5117824ec7..a516f92158f7 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroups.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroups.ps1 @@ -14,38 +14,42 @@ function Invoke-ListGroups { $Headers = $Request.Headers Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - $TenantFilter = $Request.Query.TenantFilter + $TenantFilter = $Request.Query.tenantFilter + $GroupID = $Request.Query.groupID + $GroupType = $Request.Query.groupType + $Members = $Request.Query.members + $Owners = $Request.Query.owners $SelectString = 'id,createdDateTime,displayName,description,mail,mailEnabled,mailNickname,resourceProvisioningOptions,securityEnabled,visibility,organizationId,onPremisesSamAccountName,membershipRule,groupTypes,onPremisesSyncEnabled,resourceProvisioningOptions,userPrincipalName&$expand=members($select=userPrincipalName)' $BulkRequestArrayList = [System.Collections.Generic.List[object]]::new() if ($Request.Query.GroupID) { - $SelectString = 'id,createdDateTime,displayName,description,mail,mailEnabled,mailNickname,resourceProvisioningOptions,securityEnabled,visibility,organizationId,onPremisesSamAccountName,membershipRule,groupTypes,userPrincipalName' + $SelectString = 'id,createdDateTime,displayName,description,mail,mailEnabled,mailNickname,resourceProvisioningOptions,securityEnabled,visibility,organizationId,onPremisesSamAccountName,membershipRule,groupTypes,userPrincipalName,onPremisesSyncEnabled' $BulkRequestArrayList.add(@{ id = 1 method = 'GET' - url = "groups/$($Request.Query.GroupID)?`$select=$SelectString" + url = "groups/$($GroupID)?`$select=$SelectString" }) } - if ($Request.Query.members) { + if ($Members) { $SelectString = 'id,userPrincipalName,displayName,hideFromOutlookClients,hideFromAddressLists,mail,mailEnabled,mailNickname,resourceProvisioningOptions,securityEnabled,visibility,organizationId,onPremisesSamAccountName,membershipRule' $BulkRequestArrayList.add(@{ id = 2 method = 'GET' - url = "groups/$($Request.Query.GroupID)/members?`$top=999&select=$SelectString" + url = "groups/$($GroupID)/members?`$top=999&select=$SelectString" }) } - if ($Request.Query.owners) { - if ($Request.Query.groupType -ne 'Distribution List' -and $Request.Query.groupType -ne 'Mail-Enabled Security') { + if ($Owners) { + if ($GroupType -ne 'Distribution List' -and $GroupType -ne 'Mail-Enabled Security') { $SelectString = 'id,userPrincipalName,displayName,hideFromOutlookClients,hideFromAddressLists,mail,mailEnabled,mailNickname,resourceProvisioningOptions,securityEnabled,visibility,organizationId,onPremisesSamAccountName,membershipRule' $BulkRequestArrayList.add(@{ id = 3 method = 'GET' - url = "groups/$($Request.Query.GroupID)/owners?`$top=999&select=$SelectString" + url = "groups/$($GroupID)/owners?`$top=999&select=$SelectString" }) } else { - $OwnerIds = New-ExoRequest -cmdlet 'Get-DistributionGroup' -tenantid $TenantFilter -cmdParams @{Identity = $Request.Query.GroupID } -useSystemMailbox $true | Select-Object -ExpandProperty ManagedBy + $OwnerIds = New-ExoRequest -cmdlet 'Get-DistributionGroup' -tenantid $TenantFilter -cmdParams @{Identity = $GroupID } -Select 'ManagedBy' -useSystemMailbox $true | Select-Object -ExpandProperty ManagedBy $BulkRequestArrayList.add(@{ id = 3 @@ -61,23 +65,18 @@ function Invoke-ListGroups { } } - if ($Request.Query.groupType -eq 'Distribution List' -or $Request.Query.groupType -eq 'Mail-Enabled Security') { + if ($GroupType -eq 'Distribution List' -or $GroupType -eq 'Mail-Enabled Security') { # get the outside the organization RequireSenderAuthenticationEnabled setting - $OnlyAllowInternal = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-DistributionGroup' -cmdParams @{Identity = $Request.Query.GroupID } -useSystemMailbox $true | Select-Object -ExpandProperty RequireSenderAuthenticationEnabled + $OnlyAllowInternal = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-DistributionGroup' -cmdParams @{Identity = $GroupID } -Select 'RequireSenderAuthenticationEnabled' -useSystemMailbox $true | Select-Object -ExpandProperty RequireSenderAuthenticationEnabled } elseif ($GroupType -eq 'Microsoft 365') { - $OnlyAllowInternal = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-UnifiedGroup' -cmdParams @{Identity = $Request.Query.GroupID } -useSystemMailbox $true | Select-Object -ExpandProperty RequireSenderAuthenticationEnabled + $UnifiedGroup = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-UnifiedGroup' -cmdParams @{Identity = $GroupID } -Select 'RequireSenderAuthenticationEnabled,subscriptionEnabled,AutoSubscribeNewMembers' -useSystemMailbox $true + $OnlyAllowInternal = $UnifiedGroup.RequireSenderAuthenticationEnabled } else { $OnlyAllowInternal = $null } - if ($Request.Query.groupType -eq 'Microsoft 365') { - $UnifiedGroup = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-UnifiedGroup' -cmdParams @{Identity = $Request.Query.GroupID } -useSystemMailbox $true | Select-Object -Property subscriptionEnabled, AutoSubscribeNewMembers - - if ($UnifiedGroup.subscriptionEnabled -eq $true -and $UnifiedGroup.AutoSubscribeNewMembers -eq $true) { - $SendCopies = $true - } else { - $SendCopies = $false - } + if ($GroupType -eq 'Microsoft 365') { + if ($UnifiedGroup.subscriptionEnabled -eq $true -and $UnifiedGroup.AutoSubscribeNewMembers -eq $true) { $SendCopies = $true } else { $SendCopies = $false } } else { $SendCopies = $null } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddUserBulk.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddUserBulk.ps1 index 3bb2c6b06a53..a7240624c9c1 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddUserBulk.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddUserBulk.ps1 @@ -131,7 +131,7 @@ function Invoke-AddUserBulk { if ($AssignedLicenses) { $GuidPattern = '([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})' $LicenseSkus = $AssignedLicenses.value ?? $AssignedLicenses | Where-Object { $_ -match $GuidPattern } - Set-CIPPUserLicense -User $BulkResult.id -AddLicenses $LicenseSkus -TenantFilter $TenantFilter + Set-CIPPUserLicense -UserId $BulkResult.id -AddLicenses $LicenseSkus -TenantFilter $TenantFilter } $Results.Add(@{ resultText = $Message.resultText diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-EditUser.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-EditUser.ps1 index d40f20130797..5b985cf0817e 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-EditUser.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-EditUser.ps1 @@ -98,7 +98,7 @@ function Invoke-EditUser { value = 'Set-CIPPUserLicense' } Parameters = [pscustomobject]@{ - userId = $UserObj.id + UserId = $UserObj.id APIName = 'Sherweb License Assignment' AddLicenses = $licenses } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOffboardUser.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOffboardUser.ps1 index cfff9d58c240..970d02136dfd 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOffboardUser.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOffboardUser.ps1 @@ -1,6 +1,6 @@ using namespace System.Net -Function Invoke-ExecOffboardUser { +function Invoke-ExecOffboardUser { <# .FUNCTIONALITY Entrypoint @@ -30,7 +30,7 @@ Function Invoke-ExecOffboardUser { options = $Request.Body RunScheduled = $true } - ScheduledTime = $Request.Body.scheduled.date + ScheduledTime = $Request.Body.Scheduled.date PostExecution = @{ Webhook = [bool]$Request.Body.PostExecution.webhook Email = [bool]$Request.Body.PostExecution.email diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOneDriveShortCut.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOneDriveShortCut.ps1 index 5bf461f6a0d5..4ca493e65db2 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOneDriveShortCut.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOneDriveShortCut.ps1 @@ -14,8 +14,14 @@ Function Invoke-ExecOneDriveShortCut { $Headers = $Request.Headers Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + # Interact with the body of the request + $TenantFilter = $Request.Body.tenantFilter + $Username = $Request.Body.username + $UserId = $Request.Body.userid + $URL = $Request.Body.siteUrl.value + Try { - $Result = New-CIPPOneDriveShortCut -username $Request.Body.username -userid $Request.Body.userid -TenantFilter $Request.Body.tenantFilter -URL $Request.Body.siteUrl.value -Headers $Request.Headers + $Result = New-CIPPOneDriveShortCut -Username $Username -UserId $UserId -TenantFilter $TenantFilter -URL $URL -Headers $Headers $StatusCode = [HttpStatusCode]::OK } catch { $Result = $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-EditCAPolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-EditCAPolicy.ps1 index eb3324e2ab75..755914af4aaf 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-EditCAPolicy.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-EditCAPolicy.ps1 @@ -32,7 +32,7 @@ Function Invoke-EditCAPolicy { $properties["displayName"] = $DisplayName } - $Request = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta//identity/conditionalAccess/policies/$($ID)" -tenantid $TenantFilter -type PATCH -body ($properties | ConvertTo-Json) -asapp $true + $Request = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/identity/conditionalAccess/policies/$($ID)" -tenantid $TenantFilter -type PATCH -body ($properties | ConvertTo-Json) -asapp $true $Result = "Successfully updated CA policy $($ID)" if ($State) { $Result += " state to $($State)" } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsTemplate.ps1 index c41da1262f37..b22a4b1687e0 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsTemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsTemplate.ps1 @@ -30,6 +30,15 @@ function Invoke-AddStandardsTemplate { PartitionKey = 'StandardsTemplateV2' GUID = "$GUID" } + + $AddObject = @{ + PartitionKey = 'InstanceProperties' + RowKey = 'CIPPURL' + Value = [string]([System.Uri]$Headers.'x-ms-original-url').Host + } + $ConfigTable = Get-CIPPTable -tablename 'Config' + Add-AzDataTableEntity @ConfigTable -Entity $AddObject -Force + Write-LogMessage -headers $Request.Headers -API $APINAME -message "Standards Template $($Request.body.templateName) with GUID $GUID added/edited." -Sev 'Info' $body = [pscustomobject]@{'Results' = 'Successfully added template'; Metadata = @{id = $GUID } } diff --git a/Modules/CIPPCore/Public/GraphHelper/New-TeamsAPIGetRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-TeamsAPIGetRequest.ps1 index 31f1c662b994..8d3e99ce8892 100644 --- a/Modules/CIPPCore/Public/GraphHelper/New-TeamsAPIGetRequest.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/New-TeamsAPIGetRequest.ps1 @@ -17,7 +17,7 @@ function New-TeamsAPIGetRequest($Uri, $tenantID, $Method = 'GET', $Resource = '4 'x-ms-correlation-id' = [guid]::NewGuid() 'X-Requested-With' = 'XMLHttpRequest' 'x-ms-tnm-applicationid' = '045268c0-445e-4ac1-9157-d58f67b167d9' - + 'Accept' = 'application/json' } $Data if ($noPagination) { $nextURL = $null } else { $nextURL = $data.NextLink } diff --git a/Modules/CIPPCore/Public/New-CIPPCAPolicy.ps1 b/Modules/CIPPCore/Public/New-CIPPCAPolicy.ps1 index 0e4d23694b98..8dd288691767 100644 --- a/Modules/CIPPCore/Public/New-CIPPCAPolicy.ps1 +++ b/Modules/CIPPCore/Public/New-CIPPCAPolicy.ps1 @@ -117,9 +117,9 @@ function New-CIPPCAPolicy { } } - #for each of the locations, check if they exist, if not create them. These are in $jsonobj.LocationInfo $LocationLookupTable = foreach ($locations in $jsonobj.LocationInfo) { + if (!$locations) { continue } foreach ($location in $locations) { if (!$location.displayName) { continue } $CheckExististing = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/namedLocations' -tenantid $TenantFilter -asApp $true @@ -233,7 +233,7 @@ function New-CIPPCAPolicy { $CheckExististing = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/policies' -tenantid $TenantFilter -asApp $true | Where-Object -Property displayName -EQ $displayname if ($CheckExististing) { if ($Overwrite -ne $true) { - Throw "Conditional Access Policy with Display Name $($Displayname) Already exists" + throw "Conditional Access Policy with Display Name $($Displayname) Already exists" return $false } else { Write-Information "overwriting $($CheckExististing.id)" diff --git a/Modules/CIPPCore/Public/New-CIPPOneDriveShortCut.ps1 b/Modules/CIPPCore/Public/New-CIPPOneDriveShortCut.ps1 index 29764fc40e34..d1d5ce8db072 100644 --- a/Modules/CIPPCore/Public/New-CIPPOneDriveShortCut.ps1 +++ b/Modules/CIPPCore/Public/New-CIPPOneDriveShortCut.ps1 @@ -12,11 +12,11 @@ function New-CIPPOneDriveShortCut { Write-Host "Received $Username and $UserId. We're using $URL and $TenantFilter" try { $SiteInfo = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/sites/' -tenantid $TenantFilter -asapp $true | Where-Object -Property weburl -EQ $URL - $ListItemUniqueId = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/sites/$($siteInfo.id)/drive?`$select=SharepointIds" -tenantid $TenantFilter -asapp $true).SharePointIds + $ListItemUniqueId = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/sites/$($SiteInfo.id)/drive?`$select=SharepointIds" -tenantid $TenantFilter -asapp $true).SharePointIds $body = [PSCustomObject]@{ name = 'Documents' remoteItem = @{ - SharepointIds = @{ + sharepointIds = @{ listId = $($ListItemUniqueId.listid) listItemUniqueId = 'root' siteId = $($ListItemUniqueId.siteId) @@ -26,12 +26,12 @@ function New-CIPPOneDriveShortCut { } '@microsoft.graph.conflictBehavior' = 'rename' } | ConvertTo-Json -Depth 10 - New-GraphPOSTRequest -method POST "https://graph.microsoft.com/beta/users/$username/drive/root/children" -body $body -tenantid $TenantFilter -asapp $true - Write-LogMessage -API $APIName -headers $Headers -message "Created OneDrive shortcut called $($SiteInfo.displayName) for $($username)" -Sev 'info' - return "Successfully created OneDrive Shortcut for $username called $($SiteInfo.displayName) " + New-GraphPOSTRequest -method POST "https://graph.microsoft.com/beta/users/$Username/drive/root/children" -body $Body -tenantid $TenantFilter -asapp $true + Write-LogMessage -API $APIName -headers $Headers -message "Created OneDrive shortcut called $($SiteInfo.displayName) for $($Username)" -Sev 'info' + return "Successfully created OneDrive Shortcut for $Username called $($SiteInfo.displayName) " } catch { $ErrorMessage = Get-CippException -Exception $_ - $Result = "Could not add Onedrive shortcut to $username : $($ErrorMessage.NormalizedError)" + $Result = "Could not add Onedrive shortcut to $Username : $($ErrorMessage.NormalizedError)" Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Error' -LogData $ErrorMessage throw $Result } diff --git a/Modules/CIPPCore/Public/New-CIPPUserTask.ps1 b/Modules/CIPPCore/Public/New-CIPPUserTask.ps1 index 3c228ef1006b..97c14c02d6e6 100644 --- a/Modules/CIPPCore/Public/New-CIPPUserTask.ps1 +++ b/Modules/CIPPCore/Public/New-CIPPUserTask.ps1 @@ -30,7 +30,7 @@ function New-CIPPUserTask { value = 'Set-CIPPUserLicense' } Parameters = [pscustomobject]@{ - userId = $UserObj.id + UserId = $UserObj.id APIName = 'Sherweb License Assignment' AddLicenses = $licenses } diff --git a/Modules/CIPPCore/Public/Set-CIPPGroupAuthentication.ps1 b/Modules/CIPPCore/Public/Set-CIPPGroupAuthentication.ps1 index 230afb2e3604..1bf763480b2d 100644 --- a/Modules/CIPPCore/Public/Set-CIPPGroupAuthentication.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPGroupAuthentication.ps1 @@ -15,7 +15,7 @@ function Set-CIPPGroupAuthentication( New-ExoRequest -tenantid $TenantFilter -cmdlet 'Set-UnifiedGroup' -cmdParams @{Identity = $Id; RequireSenderAuthenticationEnabled = $OnlyAllowInternal } } elseif ($GroupType -eq 'Security') { Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message 'This setting cannot be set on a security group.' -Sev 'Error' - return "$GroupType's group cannot have this setting changed" + throw "$GroupType's group cannot have this setting changed" } $Message = "Successfully set $GroupType group $Id to allow messages from people $messageSuffix" @@ -25,6 +25,6 @@ function Set-CIPPGroupAuthentication( $ErrorMessage = Get-CippException -Exception $_ $Message = "Failed to set Delivery Management: $($ErrorMessage.NormalizedError)" Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Message -Sev 'Error' -LogData $ErrorMessage - return $Message + throw $Message } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishProtection.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishProtection.ps1 index 5469ef708182..c74ea30aa0e8 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishProtection.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishProtection.ps1 @@ -35,6 +35,10 @@ function Invoke-CIPPStandardPhishProtection { $TenantId = Get-Tenants | Where-Object -Property defaultDomainName -EQ $tenant + $Table = Get-CIPPTable -TableName Config + $CippConfig = (Get-CIPPAzDataTableEntity @Table) + $CIPPUrl = ($CippConfig | Where-Object { $_.RowKey -eq 'CIPPURL' }).Value + try { $currentBody = (New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/organization/$($TenantId.customerId)/branding/localizations/0/customCSS" -tenantid $tenant) } catch { @@ -42,11 +46,22 @@ function Invoke-CIPPStandardPhishProtection { } $CSS = @" .ext-sign-in-box { - background-image: url(https://clone.cipp.app/api/PublicPhishingCheck?Tenantid=$($tenant)&URL=$($Settings.URL)); + background-image: url(https://clone.cipp.app/api/PublicPhishingCheck?Tenantid=$($tenant)&URL=https://$($CIPPUrl)); } "@ if ($Settings.remediate -eq $true) { + $malformedCSSPattern = '\.ext-sign-in-box\s*\{\s*background-image:\s*url\(https://clone\.cipp\.app/api/PublicPhishingCheck\?Tenantid=[^&]*&URL=\);\s*\}' + if ($currentBody -match $malformedCSSPattern) { + if ($Settings.remediate -eq $true) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Attempting to fix malformed PhishProtection CSS by removing the problematic pattern' -sev Info + # Remove the malformed CSS pattern + $currentBody = $currentBody -replace $malformedCSSPattern, '' + # Clean up any duplicate .ext-sign-in-box entries + #$currentBody = $currentBody -replace '\.ext-sign-in-box\s*\{[^}]*\}\s*\.ext-sign-in-box', '.ext-sign-in-box' + } + } + try { if (!$currentBody) { $AddedHeaders = @{'Accept-Language' = 0 } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRestrictThirdPartyStorageServices.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRestrictThirdPartyStorageServices.ps1 index d523b3d83174..9ee55cba203d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRestrictThirdPartyStorageServices.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRestrictThirdPartyStorageServices.ps1 @@ -59,7 +59,7 @@ function Invoke-CIPPStandardRestrictThirdPartyStorageServices { # Normal /servicePrincipal/AppId does not find the service principal, so gotta use the Upsert method. Also handles if the service principal does not exist nicely. # https://learn.microsoft.com/en-us/graph/api/serviceprincipal-upsert?view=graph-rest-beta&tabs=http $UpdateUri = "https://graph.microsoft.com/beta/servicePrincipals(appId='$AppId')" - $null = New-GraphPostRequest -Uri $UpdateUri -Body $DisableBody -TenantID $Tenant -Type PATCH + $null = New-GraphPostRequest -Uri $UpdateUri -Body $DisableBody -TenantID $Tenant -Type PATCH -AddedHeaders @{'Prefer' = 'create-if-missing'} # Refresh the current state after disabling $CurrentState = New-GraphGetRequest -Uri $Uri -tenantid $Tenant | Select-Object displayName, accountEnabled, appId diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 index e9e3daa4a36b..333788bf51e0 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 @@ -43,8 +43,10 @@ function Invoke-CIPPStandardSendReceiveLimitTenant { } $AllMailBoxPlans = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-MailboxPlan' | Select-Object DisplayName, MaxSendSize, MaxReceiveSize, GUID - $MaxSendSize = $Settings.SendLimit * 1MB - $MaxReceiveSize = $Settings.ReceiveLimit * 1MB + $MaxSendSize = "$($Settings.SendLimit)MB" + $MaxReceiveSize = "$($Settings.ReceiveLimit)MB" + $MaxSendSizeBytes = $Settings.SendLimit * 1MB + $MaxReceiveSizeBytes = $Settings.ReceiveLimit * 1MB $NotSetCorrectly = foreach ($MailboxPlan in $AllMailBoxPlans) { if ($MailboxPlan.MaxSendSize -eq 'Unlimited') { @@ -59,7 +61,7 @@ function Invoke-CIPPStandardSendReceiveLimitTenant { $PlanMaxReceiveSize = [int64]($MailboxPlan.MaxReceiveSize -replace '.*\(([\d,]+).*', '$1' -replace ',', '') } - if ($PlanMaxSendSize -ne $MaxSendSize -or $PlanMaxReceiveSize -ne $MaxReceiveSize) { + if ($PlanMaxSendSize -ne $MaxSendSizeBytes -or $PlanMaxReceiveSize -ne $MaxReceiveSizeBytes) { $MailboxPlan } } diff --git a/cspell.json b/cspell.json index e4ec9aadb5ed..b931fc283665 100644 --- a/cspell.json +++ b/cspell.json @@ -14,6 +14,7 @@ "Connectwise", "CPIM", "Datto", + "Dmarc", "DMARC", "endswith", "entra", @@ -25,6 +26,7 @@ "Intune", "locationcipp", "MAPI", + "MSCNAME", "Multitenant", "OBEE", "passwordless", diff --git a/version_latest.txt b/version_latest.txt index 8104cabd36fb..0e79152459e0 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -8.1.0 +8.1.1