From 0d062809e878f37a0dcb61c226ed13c3339259fb Mon Sep 17 00:00:00 2001 From: nicholxs <41819863+nichxlxs@users.noreply.github.com> Date: Thu, 13 Feb 2025 13:39:14 +1100 Subject: [PATCH 001/167] Fix TotalArchiveItemSize in ListUserMailboxDetails TotalArchiveItemSize is currently returning 0.0 due to trying to divide by a string with the size formatted in GB. For whatever reason, the existing method works with the normal mailbox itemsize (which uses a different API), however this should fix it for the EXO Get-MailboxStatistics method, that the Archive Mailbox is currently relying on. --- .../Users/Invoke-ListUserMailboxDetails.ps1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxDetails.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxDetails.ps1 index 512ca633f54f..aaf54bd1bf09 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxDetails.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxDetails.ps1 @@ -156,8 +156,8 @@ Function Invoke-ListUserMailboxDetails { $TotalItemSize = try { [math]::Round([float]($TotalItemSizeString[0]) / $ItemSizeType, 2) } catch { 0 } if ($ArchiveEnabled) { - $ArchiveSizeType = '1{0}' -f ($TotalArchiveItemSizeString[1] ?? 'Gb') - $TotalArchiveItemSize = [math]::Round([float]($TotalArchiveItemSizeString[0]) / $ArchiveSizeType, 2) + $TotalArchiveItemSize = try { [math]::Round([float]($TotalArchiveItemSizeString[0]), 2) } catch { 0 } + $TotalArchiveItemCount = try { [math]::Round($ArchiveSizeRequest.ItemCount, 2) } catch { 0 } } # Build the GraphRequest object @@ -177,8 +177,8 @@ Function Invoke-ListUserMailboxDetails { ProhibitSendReceiveQuota = $ProhibitSendReceiveQuota ItemCount = [math]::Round($StatsRequest.ItemCount, 2) TotalItemSize = $TotalItemSize - TotalArchiveItemSize = if ($ArchiveEnabled) { $TotalArchiveItemSize } else { '0' } - TotalArchiveItemCount = if ($ArchiveEnabled) { try { [math]::Round($ArchiveSizeRequest.ItemCount, 2) } catch { 0 } } else { 0 } + TotalArchiveItemSize = $TotalArchiveItemSize + TotalArchiveItemCount = $TotalArchiveItemCount BlockedForSpam = $BlockedForSpam ArchiveMailBox = $ArchiveEnabled AutoExpandingArchive = $AutoExpandingArchiveEnabled From f3c6a8397e9cbc03de7f7bf15f16a3cc32e02987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Fri, 14 Feb 2025 18:53:18 +0100 Subject: [PATCH 002/167] Refactor logging and state handling in CIPP standards Update comments Refactor input validation and state handling in multiple standards Comments Refactor logging and state handling in CIPP standards --- ...nvoke-CIPPStandardActivityBasedTimeout.ps1 | 31 +++--- .../Standards/Invoke-CIPPStandardAddDKIM.ps1 | 1 + .../Invoke-CIPPStandardAnonReportDisable.ps1 | 1 + .../Standards/Invoke-CIPPStandardAuditLog.ps1 | 1 + ...Invoke-CIPPStandardAuthMethodsSettings.ps1 | 15 +-- .../Standards/Invoke-CIPPStandardBookings.ps1 | 27 +++--- .../Standards/Invoke-CIPPStandardBranding.ps1 | 15 +-- .../Invoke-CIPPStandardCloudMessageRecall.ps1 | 30 +++--- ...-CIPPStandardConditionalAccessTemplate.ps1 | 2 +- .../Invoke-CIPPStandardDelegateSentItems.ps1 | 1 + ...voke-CIPPStandardDeletedUserRentention.ps1 | 33 ++++--- ...PStandardDisableAddShortcutsToOneDrive.ps1 | 7 +- .../Invoke-CIPPStandardDisableAppCreation.ps1 | 1 + ...nvoke-CIPPStandardDisableBasicAuthSMTP.ps1 | 2 + ...voke-CIPPStandardDisableGuestDirectory.ps1 | 1 + .../Invoke-CIPPStandardDisableGuests.ps1 | 2 + .../Invoke-CIPPStandardDisableReshare.ps1 | 3 +- .../Invoke-CIPPStandardDisableSMS.ps1 | 1 + ...IPPStandardDisableSharePointLegacyAuth.ps1 | 1 + ...nvoke-CIPPStandardDisableSharedMailbox.ps1 | 1 + .../Invoke-CIPPStandardDisableTNEF.ps1 | 1 + ...voke-CIPPStandardDisableTenantCreation.ps1 | 1 + ...voke-CIPPStandardDisableUserSiteCreate.ps1 | 2 +- .../Invoke-CIPPStandardDisableVoice.ps1 | 1 + ...e-CIPPStandardEXODisableAutoForwarding.ps1 | 1 + .../Invoke-CIPPStandardEnableFIDO2.ps1 | 1 + .../Invoke-CIPPStandardEnableMailTips.ps1 | 1 + ...voke-CIPPStandardEnableMailboxAuditing.ps1 | 1 + .../Invoke-CIPPStandardExcludedfileExt.ps1 | 2 +- .../Invoke-CIPPStandardExternalMFATrusted.ps1 | 25 ++--- .../Invoke-CIPPStandardFocusedInbox.ps1 | 25 ++--- ...PStandardGlobalQuarantineNotifications.ps1 | 25 ++--- .../Invoke-CIPPStandardGroupTemplate.ps1 | 2 +- .../Invoke-CIPPStandardGuestInvite.ps1 | 21 +++-- ...e-CIPPStandardIntuneComplianceSettings.ps1 | 20 ++-- .../Invoke-CIPPStandardIntuneTemplate.ps1 | 4 +- .../Invoke-CIPPStandardLegacyMFACleanup.ps1 | 1 + .../Standards/Invoke-CIPPStandardNudgeMFA.ps1 | 42 +++++---- .../Invoke-CIPPStandardOauthConsent.ps1 | 1 + ...CIPPStandardPWcompanionAppAllowedState.ps1 | 35 +++---- ...oke-CIPPStandardPasswordExpireDisabled.ps1 | 1 + .../Invoke-CIPPStandardProfilePhotos.ps1 | 30 +++--- .../Invoke-CIPPStandardRotateDKIM.ps1 | 1 + .../Invoke-CIPPStandardSPDirectSharing.ps1 | 1 + ...ke-CIPPStandardSPDisallowInfectedFiles.ps1 | 1 + .../Invoke-CIPPStandardSPEmailAttestation.ps1 | 9 +- ...e-CIPPStandardSPExternalUserExpiration.ps1 | 8 +- .../Invoke-CIPPStandardSPSyncButtonState.ps1 | 12 ++- ...nvoke-CIPPStandardSafeAttachmentPolicy.ps1 | 2 +- .../Invoke-CIPPStandardSafeSendersDisable.ps1 | 1 + .../Invoke-CIPPStandardSendFromAlias.ps1 | 1 + .../Invoke-CIPPStandardShortenMeetings.ps1 | 31 +++--- .../Invoke-CIPPStandardSpamFilterPolicy.ps1 | 94 ++++++++++--------- .../Invoke-CIPPStandardSpoofWarn.ps1 | 32 ++++--- .../Invoke-CIPPStandardStaleEntraDevices.ps1 | 4 +- .../Standards/Invoke-CIPPStandardTAP.ps1 | 21 +++-- .../Invoke-CIPPStandardTeamsEnrollUser.ps1 | 25 ++--- ...PPStandardTeamsFederationConfiguration.ps1 | 7 +- ...e-CIPPStandardTeamsGlobalMeetingPolicy.ps1 | 25 ++--- ...oke-CIPPStandardTeamsMeetingsByDefault.ps1 | 27 +++--- ...nvoke-CIPPStandardTeamsMessagingPolicy.ps1 | 28 +++--- ...voke-CIPPStandardTenantDefaultTimezone.ps1 | 2 +- ...voke-CIPPStandardTransportRuleTemplate.ps1 | 2 +- .../Invoke-CIPPStandardUserSubmissions.ps1 | 57 +++++------ .../Invoke-CIPPStandardcalDefault.ps1 | 20 ++-- .../Invoke-CIPPStandarddisableMacSync.ps1 | 2 +- .../Invoke-CIPPStandardintuneDeviceReg.ps1 | 6 +- ...CIPPStandardintuneDeviceRetirementDays.ps1 | 1 + .../Standards/Invoke-CIPPStandardlaps.ps1 | 1 + .../Invoke-CIPPStandardsharingCapability.ps1 | 40 ++++---- ...e-CIPPStandardsharingDomainRestriction.ps1 | 29 +++--- .../Invoke-CIPPStandardunmanagedSync.ps1 | 2 +- Tools/Update-StandardsComments.ps1 | 2 +- 73 files changed, 521 insertions(+), 392 deletions(-) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 index ad6778144a6a..02558d5a3716 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 @@ -17,7 +17,7 @@ function Invoke-CIPPStandardActivityBasedTimeout { "CIS" "spo_idle_session_timeout" ADDEDCOMPONENT - {"type":"select","multiple":false,"label":"Select value","name":"standards.ActivityBasedTimeout.timeout","options":[{"label":"1 Hour","value":"01:00:00"},{"label":"3 Hours","value":"03:00:00"},{"label":"6 Hours","value":"06:00:00"},{"label":"12 Hours","value":"12:00:00"},{"label":"24 Hours","value":"1.00:00:00"}]} + {"type":"autoComplete","multiple":false,"creatable":false,"label":"Select value","name":"standards.ActivityBasedTimeout.timeout","options":[{"label":"1 Hour","value":"01:00:00"},{"label":"3 Hours","value":"03:00:00"},{"label":"6 Hours","value":"06:00:00"},{"label":"12 Hours","value":"12:00:00"},{"label":"24 Hours","value":"1.00:00:00"}]} IMPACT Medium Impact POWERSHELLEQUIVALENT @@ -33,28 +33,31 @@ function Invoke-CIPPStandardActivityBasedTimeout { param($Tenant, $Settings) #$Rerun -Type Standard -Tenant $Tenant -API 'ActivityBasedTimeout' -Settings $Settings + # Get timeout value using null-coalescing operator + $timeout = $Settings.timeout.value ?? $Settings.timeout + # 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 + if ([string]::IsNullOrWhiteSpace($timeout) -or $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' } + if ($null -eq $timeout ) { $timeout = '01:00:00' } - $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/activityBasedTimeoutPolicies' -tenantid $tenant - $StateIsCorrect = if ($CurrentState.definition -like "*$($Settings.timeout)*") { $true } else { $false } + $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/activityBasedTimeoutPolicies' -tenantid $Tenant + $StateIsCorrect = if ($CurrentState.definition -like "*$timeout*") { $true } else { $false } If ($Settings.remediate -eq $true) { try { if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Activity Based Timeout is already enabled and set to $($Settings.timeout)" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Activity Based Timeout is already enabled and set to $timeout" -sev Info } else { $PolicyTemplate = @{ displayName = 'DefaultTimeoutPolicy' isOrganizationDefault = $true definition = @( - "{`"ActivityBasedTimeoutPolicy`":{`"Version`":1,`"ApplicationPolicies`":[{`"ApplicationId`":`"default`",`"WebSessionIdleTimeout`":`"$($Settings.timeout)`"}]}}" + "{`"ActivityBasedTimeoutPolicy`":{`"Version`":1,`"ApplicationPolicies`":[{`"ApplicationId`":`"default`",`"WebSessionIdleTimeout`":`"$timeout`"}]}}" ) } $body = ConvertTo-Json -InputObject $PolicyTemplate -Depth 10 -Compress @@ -67,26 +70,26 @@ function Invoke-CIPPStandardActivityBasedTimeout { $RequestType = 'PATCH' $URI = "https://graph.microsoft.com/beta/policies/activityBasedTimeoutPolicies/$($CurrentState.id)" } - New-GraphPostRequest -tenantid $tenant -Uri $URI -Type $RequestType -Body $body -ContentType 'application/json' - Write-LogMessage -API 'Standards' -tenant $tenant -message "Enabled Activity Based Timeout with a value of $($Settings.timeout)" -sev Info + New-GraphPostRequest -tenantid $Tenant -Uri $URI -Type $RequestType -Body $body -ContentType 'application/json' + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Enabled Activity Based Timeout with a value of $timeout" -sev Info } } catch { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to enable Activity Based Timeout a value of $($Settings.timeout)." -sev Error -LogData $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to enable Activity Based Timeout a value of $timeout." -sev Error -LogData $_ } } if ($Settings.alert -eq $true) { if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Activity Based Timeout is enabled and set to $($Settings.timeout)" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Activity Based Timeout is enabled and set to $timeout" -sev Info } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Activity Based Timeout is not set to $($Settings.timeout)" -sev Alert + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Activity Based Timeout is not set to $timeout" -sev Alert } } if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'ActivityBasedTimeout' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant + Add-CIPPBPAField -FieldName 'ActivityBasedTimeout' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 index df9c1b8c58e5..7d16160baeef 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 @@ -22,6 +22,7 @@ function Invoke-CIPPStandardAddDKIM { New-DkimSigningConfig and Set-DkimSigningConfig RECOMMENDEDBY "CIS" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAnonReportDisable.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAnonReportDisable.ps1 index 1eeaae1b89fb..668323a5173e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAnonReportDisable.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAnonReportDisable.ps1 @@ -20,6 +20,7 @@ function Invoke-CIPPStandardAnonReportDisable { POWERSHELLEQUIVALENT Update-MgBetaAdminReportSetting -BodyParameter @{displayConcealedNames = \$true} RECOMMENDEDBY + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 index 3c5243f8e732..079371875e27 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 @@ -23,6 +23,7 @@ function Invoke-CIPPStandardAuditLog { Enable-OrganizationCustomization RECOMMENDEDBY "CIS" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuthMethodsSettings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuthMethodsSettings.ps1 index b379d603c4b4..5cfd3d47d35f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuthMethodsSettings.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuthMethodsSettings.ps1 @@ -7,22 +7,25 @@ function Invoke-CIPPStandardAuthMethodsSettings { .SYNOPSIS (Label) Configure Authentication Methods Policy Settings .DESCRIPTION - (Helptext) Configures the report suspicious activity settings and system credential preferences in the authentication methods policy - (DocsDescription) This standard allows you to configure the reportSuspiciousActivitySettings and systemCredentialPreferences properties within the authentication methods policy. + (Helptext) Configures the report suspicious activity settings and system credential preferences in the authentication methods policy. + (DocsDescription) Controls the authentication methods policy settings for reporting suspicious activity and system credential preferences. These settings help enhance the security of authentication in your organization. .NOTES CAT - Entra Standards + Entra (AAD) Standards TAG "lowimpact" ADDEDCOMPONENT - {"type":"autoComplete","multiple":false,"name":"standards.AuthMethodsSettings.ReportSuspiciousActivity","label":"Report Suspicious Activity Settings","options":[{"label":"Default","value":"default"},{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} - {"type":"autoComplete","multiple":false,"name":"standards.AuthMethodsSettings.SystemCredential","label":"System Credential Preferences","options":[{"label":"Default","value":"default"},{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} + {"type":"autoComplete","multiple":false,"creatable":false,"required":false,"name":"standards.AuthMethodsSettings.ReportSuspiciousActivity","label":"Report Suspicious Activity Settings","options":[{"label":"Microsoft managed","value":"default"},{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} + {"type":"autoComplete","multiple":false,"creatable":false,"required":false,"name":"standards.AuthMethodsSettings.SystemCredential","label":"System Credential Preferences","options":[{"label":"Microsoft managed","value":"default"},{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} IMPACT Low Impact POWERSHELLEQUIVALENT Update-MgBetaPolicyAuthenticationMethodPolicy + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/global-standards#low-impact + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/entra-aad-standards#low-impact #> param($Tenant, $Settings) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 index 738ef7844b91..b1f5e7fece95 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 @@ -15,7 +15,7 @@ function Invoke-CIPPStandardBookings { TAG "mediumimpact" ADDEDCOMPONENT - {"type":"select","multiple":false,"label":"Select value","name":"standards.Bookings.state","options":[{"label":"Enabled","value":"true"},{"label":"Disabled","value":"false"}]} + {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.Bookings.state","options":[{"label":"Enabled","value":"true"},{"label":"Disabled","value":"false"}]} IMPACT Medium Impact POWERSHELLEQUIVALENT @@ -30,42 +30,45 @@ function Invoke-CIPPStandardBookings { param($Tenant, $Settings) ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'Bookings' + # Get state value using null-coalescing operator + $state = $Settings.state.value ?? $Settings.state + $CurrentState = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig').BookingsEnabled - $WantedState = if ($Settings.state -eq 'true') { $true } else { $false } + $WantedState = if ($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 + 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 + if (([string]::IsNullOrWhiteSpace($state) -or $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) { try { - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdParams @{ BookingsEnabled = $WantedState } -useSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully set the tenant Bookings state to $($Settings.state)" -sev Info + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdParams @{ BookingsEnabled = $WantedState } -useSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Successfully set the tenant Bookings state to $state" -sev Info } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set the tenant Bookings state to $($Settings.state). Error: $ErrorMessage" -sev Error + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set the tenant Bookings state to $state. Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage } } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant Bookings state is already set correctly to $($Settings.state)" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "The tenant Bookings state is already set correctly to $state" -sev Info } } if ($Settings.alert -eq $true) { if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant Bookings is set correctly to $($Settings.state)" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "The tenant Bookings is set correctly to $state" -sev Info } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant Bookings is not set correctly to $($Settings.state)" -sev Alert + Write-LogMessage -API 'Standards' -tenant $Tenant -message "The tenant Bookings is not set correctly to $state" -sev Alert } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBranding.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBranding.ps1 index 6c28b2d8baf5..6f6529aa37bf 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBranding.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBranding.ps1 @@ -18,7 +18,7 @@ function Invoke-CIPPStandardBranding { {"type":"textField","name":"standards.Branding.signInPageText","label":"Sign-in page text","required":false} {"type":"textField","name":"standards.Branding.usernameHintText","label":"Username hint Text","required":false} {"type":"switch","name":"standards.Branding.hideAccountResetCredentials","label":"Hide self-service password reset"} - {"type":"select","multiple":false,"label":"Visual Template","name":"standards.Branding.layoutTemplateType","options":[{"label":"Full-screen background","value":"default"},{"label":"Partial-screen background","value":"verticalSplit"}]} + {"type":"autoComplete","multiple":false,"label":"Visual Template","name":"standards.Branding.layoutTemplateType","options":[{"label":"Full-screen background","value":"default"},{"label":"Partial-screen background","value":"verticalSplit"}]} {"type":"switch","name":"standards.Branding.isHeaderShown","label":"Show header"} {"type":"switch","name":"standards.Branding.isFooterShown","label":"Show footer"} IMPACT @@ -44,10 +44,13 @@ 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 } + # Get layoutTemplateType value using null-coalescing operator + $layoutTemplateType = $Settings.layoutTemplateType.value ?? $Settings.layoutTemplateType + $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 + ($CurrentState.loginPageLayoutConfiguration.layoutTemplateType -eq $layoutTemplateType) -and ($CurrentState.loginPageLayoutConfiguration.isHeaderShown -eq $Settings.isHeaderShown) -and ($CurrentState.loginPageLayoutConfiguration.isFooterShown -eq $Settings.isFooterShown) @@ -69,17 +72,17 @@ function Invoke-CIPPStandardBranding { hideAccountResetCredentials = $Settings.hideAccountResetCredentials } loginPageLayoutConfiguration = [pscustomobject]@{ - layoutTemplateType = $Settings.layoutTemplateType + layoutTemplateType = $layoutTemplateType isHeaderShown = $Settings.isHeaderShown isFooterShown = $Settings.isFooterShown } } | ConvertTo-Json -Compress } - New-GraphPostRequest @GraphRequest + $null = New-GraphPostRequest @GraphRequest 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 + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to update branding. Error: $($ErrorMessage.NormalizedError)" -Sev Error -LogData $ErrorMessage } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 index 384c50ee66e2..1c22840862c0 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 @@ -15,7 +15,7 @@ function Invoke-CIPPStandardCloudMessageRecall { TAG "lowimpact" ADDEDCOMPONENT - {"type":"select","multiple":false,"label":"Select value","name":"standards.CloudMessageRecall.state","options":[{"label":"Enabled","value":"true"},{"label":"Disabled","value":"false"}]} + {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.CloudMessageRecall.state","options":[{"label":"Enabled","value":"true"},{"label":"Disabled","value":"false"}]} IMPACT Low Impact POWERSHELLEQUIVALENT @@ -30,19 +30,22 @@ function Invoke-CIPPStandardCloudMessageRecall { param($Tenant, $Settings) ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'CloudMessageRecall' + # Get state value using null-coalescing operator + $state = $Settings.state.value ?? $Settings.state + $CurrentState = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig').MessageRecallEnabled - $WantedState = if ($Settings.state -eq 'true') { $true } else { $false } + $WantedState = if ($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 + 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 + if (([string]::IsNullOrWhiteSpace($state) -or $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 } @@ -50,26 +53,23 @@ function Invoke-CIPPStandardCloudMessageRecall { Write-Host 'Time to remediate' if ($StateIsCorrect -eq $false) { try { - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdParams @{ MessageRecallEnabled = $WantedState } -useSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully set the tenant Message Recall state to $($Settings.state)" -sev Info + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdParams @{ MessageRecallEnabled = $WantedState } -useSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Successfully set the tenant Message Recall state to $state" -sev Info } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set the tenant Message Recall state to $($Settings.state). Error: $ErrorMessage" -sev Error + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set the tenant Message Recall state to $state. Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage } } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant Message Recall state is already set correctly to $($Settings.state)" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "The tenant Message Recall state is already set correctly to $state" -sev Info } } if ($Settings.alert -eq $true) { if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant Message Recall is set correctly to $($Settings.state)" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "The tenant Message Recall is set correctly to $state" -sev Info } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant Message Recall is not set correctly to $($Settings.state)" -sev Alert + Write-LogMessage -API 'Standards' -tenant $Tenant -message "The tenant Message Recall is not set correctly to $state" -sev Alert } } - - - } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccessTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccessTemplate.ps1 index 9c2e705610b7..b4fd5026f806 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccessTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccessTemplate.ps1 @@ -15,7 +15,7 @@ function Invoke-CIPPStandardConditionalAccessTemplate { MULTIPLE True DISABLEDFEATURES - + IMPACT High ADDEDCOMPONENT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 index 0bb37f43d770..2132294d31ca 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 @@ -15,6 +15,7 @@ function Invoke-CIPPStandardDelegateSentItems { TAG "mediumimpact" ADDEDCOMPONENT + {"type":"switch","label":"Include user mailboxes","name":"standards.DelegateSentItems.IncludeUserMailboxes"} IMPACT Medium Impact POWERSHELLEQUIVALENT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 index 0d90e2a0e4ff..8db43324ab39 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 @@ -15,11 +15,11 @@ function Invoke-CIPPStandardDeletedUserRentention { TAG "lowimpact" ADDEDCOMPONENT - {"type":"select","multiple":false,"name":"standards.DeletedUserRentention.Days","label":"Retention time (Default 30 days)","options":[{"label":"30 days","value":"30"},{"label":"90 days","value":"90"},{"label":"1 year","value":"365"},{"label":"2 years","value":"730"},{"label":"3 years","value":"1095"},{"label":"4 years","value":"1460"},{"label":"5 years","value":"1825"},{"label":"6 years","value":"2190"},{"label":"7 years","value":"2555"},{"label":"8 years","value":"2920"},{"label":"9 years","value":"3285"},{"label":"10 years","value":"3650"}]} + {"type":"autoComplete","multiple":false,"name":"standards.DeletedUserRentention.Days","label":"Retention time (Default 30 days)","options":[{"label":"30 days","value":"30"},{"label":"90 days","value":"90"},{"label":"1 year","value":"365"},{"label":"2 years","value":"730"},{"label":"3 years","value":"1095"},{"label":"4 years","value":"1460"},{"label":"5 years","value":"1825"},{"label":"6 years","value":"2190"},{"label":"7 years","value":"2555"},{"label":"8 years","value":"2920"},{"label":"9 years","value":"3285"},{"label":"10 years","value":"3650"}]} IMPACT Low Impact POWERSHELLEQUIVALENT - Update-MgBetaAdminSharepointSetting + Update-MgBetaAdminSharePointSetting RECOMMENDEDBY UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block @@ -33,20 +33,23 @@ function Invoke-CIPPStandardDeletedUserRentention { $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'DeletedUserRentention' -FieldValue $CurrentInfo.deletedUserPersonalSiteRetentionPeriodInDays -StoreAs string -Tenant $tenant + Add-CIPPBPAField -FieldName 'DeletedUserRentention' -FieldValue $CurrentInfo.deletedUserPersonalSiteRetentionPeriodInDays -StoreAs string -Tenant $Tenant } + # Get days value using null-coalescing operator + $Days = $Settings.Days.value ?? $Settings.Days + # Input validation - if (($Settings.Days -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'DeletedUserRententio: Invalid Days parameter set' -sev Error + if (($Days -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'DeletedUserRentention: Invalid Days parameter set' -sev Error Return } # Backwards compatibility for v5.9.4 and back - if ($null -eq $Settings.Days) { + if ([string]::IsNullOrWhiteSpace($Days)) { $WantedState = 365 } else { - $WantedState = [int]$Settings.Days + $WantedState = [int]$Days } $StateSetCorrectly = if ($CurrentInfo.deletedUserPersonalSiteRetentionPeriodInDays -eq $WantedState) { $true } else { $false } @@ -57,26 +60,26 @@ function Invoke-CIPPStandardDeletedUserRentention { if ($StateSetCorrectly -eq $false) { try { $body = [PSCustomObject]@{ - deletedUserPersonalSiteRetentionPeriodInDays = $Settings.Days + deletedUserPersonalSiteRetentionPeriodInDays = $Days } $body = ConvertTo-Json -InputObject $body -Depth 5 -Compress - New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -AsApp $true -Type PATCH -Body $body -ContentType 'application/json' + $null = New-GraphPostRequest -tenantid $Tenant -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -AsApp $true -Type PATCH -Body $body -ContentType 'application/json' - Write-LogMessage -API 'Standards' -tenant $tenant -message "Set deleted user rentention of OneDrive to $WantedState days(s)" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Set deleted user retention of OneDrive to $WantedState day(s)" -sev Info } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set deleted user rentention of OneDrive to $WantedState days(s). Error: $ErrorMessage" -sev Error + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set deleted user retention of OneDrive to $WantedState day(s). Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage } } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Deleted user rentention of OneDrive is already set to $WantedState days(s)" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Deleted user retention of OneDrive is already set to $WantedState day(s)" -sev Info } } if ($Settings.alert -eq $true) { if ($StateSetCorrectly -eq $true) { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Deleted user rentention of OneDrive is set to $WantedState days(s)" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Deleted user retention of OneDrive is set to $WantedState day(s)" -sev Info } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Deleted user rentention of OneDrive is not set to $WantedState days(s). Value is: $($CurrentInfo.deletedUserPersonalSiteRetentionPeriodInDays) day(s)." -sev Alert + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Deleted user retention of OneDrive is not set to $WantedState day(s). Current value is: $($CurrentInfo.deletedUserPersonalSiteRetentionPeriodInDays) day(s)." -sev Alert } } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 index a09a7fa3daf7..3ac6d6d19897 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 @@ -15,7 +15,7 @@ function Invoke-CIPPStandardDisableAddShortcutsToOneDrive { TAG "mediumimpact" ADDEDCOMPONENT - {"type":"autoComplete","multiple":false,"label":"Add Shortcuts To OneDrive button state","name":"standards.DisableAddShortcutsToOneDrive.state","options":[{"label":"Disabled","value":"true"},{"label":"Enabled","value":"false"}]} + {"type":"autoComplete","multiple":false,"creatable":false,"label":"Add Shortcuts To OneDrive button state","name":"standards.DisableAddShortcutsToOneDrive.state","options":[{"label":"Disabled","value":"true"},{"label":"Enabled","value":"false"}]} IMPACT Medium Impact POWERSHELLEQUIVALENT @@ -37,12 +37,13 @@ function Invoke-CIPPStandardDisableAddShortcutsToOneDrive { } # Input validation - if (([string]::IsNullOrWhiteSpace($Settings.state) -or $Settings.state -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { + $StateValue = $Settings.state.value ?? $Settings.state + if (([string]::IsNullOrWhiteSpace($StateValue) -or $StateValue -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { Write-LogMessage -API 'Standards' -tenant $tenant -message 'DisableAddShortcutsToOneDrive: Invalid state parameter set' -sev Error Return } - $WantedState = [System.Convert]::ToBoolean($Settings.state) + $WantedState = [System.Convert]::ToBoolean($StateValue) $StateIsCorrect = if ($CurrentState.DisableAddToOneDrive -eq $WantedState) { $true } else { $false } $HumanReadableState = if ($WantedState -eq $true) { 'disabled' } else { 'enabled' } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAppCreation.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAppCreation.ps1 index ac75add64456..f96fcbb29bb4 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAppCreation.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAppCreation.ps1 @@ -22,6 +22,7 @@ function Invoke-CIPPStandardDisableAppCreation { Update-MgPolicyAuthorizationPolicy RECOMMENDEDBY "CIS" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 index 73c9716025cf..99ada42f790d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 @@ -20,6 +20,8 @@ function Invoke-CIPPStandardDisableBasicAuthSMTP { POWERSHELLEQUIVALENT Set-TransportConfig -SmtpClientAuthenticationDisabled \$true RECOMMENDEDBY + "CIS" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuestDirectory.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuestDirectory.ps1 index 55c188bda32e..1c1468dbfa6a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuestDirectory.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuestDirectory.ps1 @@ -20,6 +20,7 @@ function Invoke-CIPPStandardDisableGuestDirectory { POWERSHELLEQUIVALENT Set-AzureADMSAuthorizationPolicy -GuestUserRoleId '2af84b1e-32c8-42b7-82bc-daa82404023b' RECOMMENDEDBY + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuests.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuests.ps1 index 32e3d2a345a4..e7d070a4fbae 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuests.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuests.ps1 @@ -20,6 +20,8 @@ function Invoke-CIPPStandardDisableGuests { POWERSHELLEQUIVALENT Graph API RECOMMENDEDBY + "CIS" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 index 2c9a435131d7..72eec7f32183 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 @@ -19,9 +19,10 @@ function Invoke-CIPPStandardDisableReshare { IMPACT High Impact POWERSHELLEQUIVALENT - Update-MgBetaAdminSharepointSetting + Update-MgBetaAdminSharePointSetting RECOMMENDEDBY "CIS" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSMS.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSMS.ps1 index a9a6e9deeff3..2b3c2764f1e1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSMS.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSMS.ps1 @@ -20,6 +20,7 @@ function Invoke-CIPPStandardDisableSMS { POWERSHELLEQUIVALENT Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration RECOMMENDEDBY + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharePointLegacyAuth.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharePointLegacyAuth.ps1 index 37b894544638..d92d900faceb 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharePointLegacyAuth.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharePointLegacyAuth.ps1 @@ -23,6 +23,7 @@ function Invoke-CIPPStandardDisableSharePointLegacyAuth { Set-SPOTenant -LegacyAuthProtocolsEnabled \$false RECOMMENDEDBY "CIS" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharedMailbox.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharedMailbox.ps1 index 7a42cc0ec788..767d670878d7 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharedMailbox.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharedMailbox.ps1 @@ -22,6 +22,7 @@ function Invoke-CIPPStandardDisableSharedMailbox { Get-Mailbox & Update-MgUser RECOMMENDEDBY "CIS" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 index 4ad21eb72c6c..1e0f01ee4bcc 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 @@ -20,6 +20,7 @@ function Invoke-CIPPStandardDisableTNEF { POWERSHELLEQUIVALENT Set-RemoteDomain -Identity 'Default' -TNEFEnabled \$false RECOMMENDEDBY + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTenantCreation.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTenantCreation.ps1 index 1a2ebea5f2f0..3dac87cd1b13 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTenantCreation.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTenantCreation.ps1 @@ -22,6 +22,7 @@ function Invoke-CIPPStandardDisableTenantCreation { Update-MgPolicyAuthorizationPolicy RECOMMENDEDBY "CIS" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 index 9f2d1a96dfde..b61bf1529281 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 @@ -18,7 +18,7 @@ function Invoke-CIPPStandardDisableUserSiteCreate { IMPACT High Impact POWERSHELLEQUIVALENT - Update-MgAdminSharepointSetting + Update-MgAdminSharePointSetting RECOMMENDEDBY UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableVoice.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableVoice.ps1 index d52dd3afedd0..907326273211 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableVoice.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableVoice.ps1 @@ -20,6 +20,7 @@ function Invoke-CIPPStandardDisableVoice { POWERSHELLEQUIVALENT Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration RECOMMENDEDBY + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 index 8705dcd630cb..e3ccc3e5eb51 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 @@ -24,6 +24,7 @@ function Invoke-CIPPStandardEXODisableAutoForwarding { Set-HostedOutboundSpamFilterPolicy -AutoForwardingMode 'Off' RECOMMENDEDBY "CIS" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableFIDO2.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableFIDO2.ps1 index d76014e535dc..9848446c8756 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableFIDO2.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableFIDO2.ps1 @@ -20,6 +20,7 @@ function Invoke-CIPPStandardEnableFIDO2 { POWERSHELLEQUIVALENT Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration RECOMMENDEDBY + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 index e5211d2eda92..decc028041c0 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 @@ -24,6 +24,7 @@ function Invoke-CIPPStandardEnableMailTips { Set-OrganizationConfig RECOMMENDEDBY "CIS" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 index dac3185d381a..6bb48f4cc888 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 @@ -23,6 +23,7 @@ function Invoke-CIPPStandardEnableMailboxAuditing { Set-OrganizationConfig -AuditDisabled \$false RECOMMENDEDBY "CIS" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 index f28b6984c1c9..4f1e011bb007 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 @@ -19,7 +19,7 @@ function Invoke-CIPPStandardExcludedfileExt { IMPACT High Impact POWERSHELLEQUIVALENT - Update-MgAdminSharepointSetting + Update-MgAdminSharePointSetting RECOMMENDEDBY UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 index 95f28b7c2cd9..59f66f0f41c5 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 @@ -15,7 +15,7 @@ function Invoke-CIPPStandardExternalMFATrusted { TAG "lowimpact" ADDEDCOMPONENT - {"type":"select","multiple":false,"label":"Select value","name":"standards.ExternalMFATrusted.state","options":[{"label":"Enabled","value":"true"},{"label":"Disabled","value":"false"}]} + {"type":"autoComplete","multiple":false,"creatable":false,"label":"Select value","name":"standards.ExternalMFATrusted.state","options":[{"label":"Enabled","value":"true"},{"label":"Disabled","value":"false"}]} IMPACT Low Impact POWERSHELLEQUIVALENT @@ -31,17 +31,20 @@ function Invoke-CIPPStandardExternalMFATrusted { ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'ExternalMFATrusted' $ExternalMFATrusted = (New-GraphGetRequest -uri 'https://graph.microsoft.com/v1.0/policies/crossTenantAccessPolicy/default?$select=inboundTrust' -tenantid $Tenant) - $WantedState = if ($Settings.state -eq 'true') { $true } else { $false } + + # Get state value using null-coalescing operator + $state = $Settings.state.value ?? $Settings.state + $WantedState = if ($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 + 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 + if (([string]::IsNullOrWhiteSpace($state) -or $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 } @@ -49,17 +52,17 @@ function Invoke-CIPPStandardExternalMFATrusted { Write-Host 'Remediate External MFA Trusted' if ($ExternalMFATrusted.inboundTrust.isMfaAccepted -eq $WantedState ) { - Write-LogMessage -API 'Standards' -tenant $tenant -message "External MFA Trusted is already $StateMessage." -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "External MFA Trusted is already $StateMessage." -sev Info } else { try { $NewBody = $ExternalMFATrusted $NewBody.inboundTrust.isMfaAccepted = $WantedState $NewBody = ConvertTo-Json -Depth 10 -InputObject $NewBody -Compress - $null = New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/v1.0/policies/crossTenantAccessPolicy/default' -Type patch -Body $NewBody -ContentType 'application/json' - Write-LogMessage -API 'Standards' -tenant $tenant -message "Set External MFA Trusted to $StateMessage." -sev Info + $null = New-GraphPostRequest -tenantid $Tenant -Uri 'https://graph.microsoft.com/v1.0/policies/crossTenantAccessPolicy/default' -Type patch -Body $NewBody -ContentType 'application/json' + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Set External MFA Trusted to $StateMessage." -sev Info } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set External MFA Trusted to $StateMessage. Error: $ErrorMessage" -sev Error + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set External MFA Trusted to $StateMessage. Error: $ErrorMessage" -sev Error } } } @@ -67,9 +70,9 @@ function Invoke-CIPPStandardExternalMFATrusted { if ($Settings.alert -eq $true) { if ($ExternalMFATrusted.inboundTrust.isMfaAccepted -eq $WantedState) { - Write-LogMessage -API 'Standards' -tenant $tenant -message "External MFA Trusted is $StateMessage." -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "External MFA Trusted is $StateMessage." -sev Info } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message "External MFA Trusted is not $StateMessage." -sev Alert + Write-LogMessage -API 'Standards' -tenant $Tenant -message "External MFA Trusted is not $StateMessage." -sev Alert } } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 index adface2383c8..809f1d855d91 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 @@ -15,7 +15,7 @@ function Invoke-CIPPStandardFocusedInbox { TAG "lowimpact" ADDEDCOMPONENT - {"type":"select","multiple":false,"label":"Select value","name":"standards.FocusedInbox.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} + {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.FocusedInbox.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} IMPACT Low Impact POWERSHELLEQUIVALENT @@ -30,29 +30,32 @@ function Invoke-CIPPStandardFocusedInbox { param($Tenant, $Settings) ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'FocusedInbox' + # Get state value using null-coalescing operator + $state = $Settings.state.value ?? $Settings.state + # Input validation - if ([string]::IsNullOrWhiteSpace($Settings.state) -or $Settings.state -eq 'Select a value') { + if ([string]::IsNullOrWhiteSpace($state) -or $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 - $WantedState = if ($Settings.state -eq 'enabled') { $true } else { $false } + $WantedState = if ($state -eq 'enabled') { $true } else { $false } $StateIsCorrect = if ($CurrentState -eq $WantedState) { $true } else { $false } if ($Settings.remediate -eq $true) { Write-Host 'Time to remediate' if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Focused Inbox is already set to $($Settings.state)." -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Focused Inbox is already set to $state." -sev Info } else { try { - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdparams @{ FocusedInboxOn = $WantedState } - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Set Focused Inbox state to $($Settings.state)." -sev Info + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdParams @{ FocusedInboxOn = $WantedState } + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Set Focused Inbox state to $state." -sev Info } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Focused Inbox state to $($Settings.state). Error: $ErrorMessage" -sev Error + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Focused Inbox state to $state. Error: $($ErrorMessage.NormalizedError)" -sev Error } } } @@ -60,13 +63,13 @@ function Invoke-CIPPStandardFocusedInbox { if ($Settings.alert -eq $true) { if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Focused Inbox is set to $($Settings.state)." -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Focused Inbox is set to $state." -sev Info } else { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Focused Inbox is not set to $($Settings.state)." -sev Alert + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Focused Inbox is not set to $state." -sev Alert } } if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'FocusedInboxCorrectState' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant + Add-CIPPBPAField -FieldName 'FocusedInboxCorrectState' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 index 8b1fd25e48b3..a708c8ea6bc9 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 @@ -15,7 +15,7 @@ function Invoke-CIPPStandardGlobalQuarantineNotifications { TAG "lowimpact" ADDEDCOMPONENT - {"type":"select","multiple":false,"label":"Select value","name":"standards.GlobalQuarantineNotifications.NotificationInterval","options":[{"label":"4 hours","value":"04:00:00"},{"label":"1 day/Daily","value":"1.00:00:00"},{"label":"7 days/Weekly","value":"7.00:00:00"}]} + {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.GlobalQuarantineNotifications.NotificationInterval","options":[{"label":"4 hours","value":"04:00:00"},{"label":"1 day/Daily","value":"1.00:00:00"},{"label":"7 days/Weekly","value":"7.00:00:00"}]} IMPACT Low Impact POWERSHELLEQUIVALENT @@ -44,29 +44,32 @@ function Invoke-CIPPStandardGlobalQuarantineNotifications { if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'GlobalQuarantineNotificationsSet' -FieldValue [string]$CurrentState.EndUserSpamNotificationFrequency -StoreAs string -Tenant $tenant + Add-CIPPBPAField -FieldName 'GlobalQuarantineNotificationsSet' -FieldValue [string]$CurrentState.EndUserSpamNotificationFrequency -StoreAs string -Tenant $Tenant } + # Get notification interval using null-coalescing operator + $NotificationInterval = $Settings.NotificationInterval.value ?? $Settings.NotificationInterval + # Input validation try { - $WantedState = [timespan]$Settings.NotificationInterval + $WantedState = [timespan]$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 + Write-LogMessage -API 'Standards' -tenant $Tenant -message "GlobalQuarantineNotifications: Invalid NotificationInterval parameter set. Error: $ErrorMessage" -sev Error Return } if ($Settings.remediate -eq $true) { - Write-Host 'Time to remediate' + if ($CurrentState.EndUserSpamNotificationFrequency -eq $WantedState) { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Global Quarantine Notifications are already set to the desired value of $WantedState" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Global Quarantine Notifications are already set to the desired value of $WantedState" -sev Info } else { try { - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-QuarantinePolicy' -cmdParams @{Identity = $CurrentState.Identity; EndUserSpamNotificationFrequency = [string]$WantedState } -useSystemmailbox $true - Write-LogMessage -API 'Standards' -tenant $tenant -message "Set Global Quarantine Notifications to $WantedState" -sev Info + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-QuarantinePolicy' -cmdParams @{Identity = $CurrentState.Identity; EndUserSpamNotificationFrequency = [string]$WantedState } -useSystemmailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Set Global Quarantine Notifications to $WantedState" -sev Info } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set Global Quarantine Notifications to $WantedState. Error: $ErrorMessage" -sev Error + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Global Quarantine Notifications to $WantedState. Error: $ErrorMessage" -sev Error } } } @@ -74,9 +77,9 @@ 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 + 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 + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Global Quarantine Notifications are not set to the desired value of $WantedState" -sev Alert } } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 index cee0f39dc6e3..5cbbd7077d9e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 @@ -15,7 +15,7 @@ function Invoke-CIPPStandardGroupTemplate { CAT Templates DISABLEDFEATURES - + IMPACT Medium ADDEDCOMPONENT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGuestInvite.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGuestInvite.ps1 index 5193b69708fb..6ffdc6aab406 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGuestInvite.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGuestInvite.ps1 @@ -15,11 +15,11 @@ function Invoke-CIPPStandardGuestInvite { TAG "mediumimpact" ADDEDCOMPONENT - {"type":"autoComplete","multiple":false,"label":"Who can send invites?","name":"standards.GuestInvite.allowInvitesFrom","options":[{"label":"Everyone","value":"everyone"},{"label":"Admins, Guest inviters and All Members","value":"adminsGuestInvitersAndAllMembers"},{"label":"Admins and Guest inviters","value":"adminsAndGuestInviters"},{"label":"None","value":"none"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Who can send invites?","name":"standards.GuestInvite.allowInvitesFrom","options":[{"label":"Everyone","value":"everyone"},{"label":"Admins, Guest inviters and All Members","value":"adminsGuestInvitersAndAllMembers"},{"label":"Admins and Guest inviters","value":"adminsAndGuestInviters"},{"label":"None","value":"none"}]} IMPACT Medium Impact POWERSHELLEQUIVALENT - + RECOMMENDEDBY UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block @@ -31,7 +31,14 @@ function Invoke-CIPPStandardGuestInvite { $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' -tenantid $Tenant - $StateIsCorrect = ($CurrentState.allowInvitesFrom -eq $Settings.allowInvitesFrom.value) + # Input validation and value handling + $AllowInvitesFromValue = $Settings.allowInvitesFrom.value ?? $Settings.allowInvitesFrom + if (([string]::IsNullOrWhiteSpace($AllowInvitesFromValue) -or $AllowInvitesFromValue -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'GuestInvite: Invalid allowInvitesFrom parameter set' -sev Error + Return + } + + $StateIsCorrect = ($CurrentState.allowInvitesFrom -eq $AllowInvitesFromValue) if ($Settings.remediate -eq $true) { if ($StateIsCorrect -eq $true) { @@ -40,18 +47,18 @@ function Invoke-CIPPStandardGuestInvite { try { $GraphRequest = @{ tenantID = $Tenant - uri = "https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy" + uri = 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' AsApp = $false Type = 'PATCH' ContentType = 'application/json; charset=utf-8' Body = [pscustomobject]@{ - allowInvitesFrom = $Settings.allowInvitesFrom.value + allowInvitesFrom = $AllowInvitesFromValue } | ConvertTo-Json -Compress } New-GraphPostRequest @GraphRequest - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Successfully updated Guest Invite setting to $($Settings.allowInvitesFrom.value)" -Sev Info + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Successfully updated Guest Invite setting to $AllowInvitesFromValue" -Sev Info } catch { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to update Guest Invite setting to $($Settings.allowInvitesFrom.value)" -Sev Error -LogData $_ + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to update Guest Invite setting to $AllowInvitesFromValue" -Sev Error -LogData $_ } } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 index d8ca6d499c9f..3fd021180a2a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 @@ -15,12 +15,12 @@ function Invoke-CIPPStandardIntuneComplianceSettings { TAG "lowimpact" ADDEDCOMPONENT - {"type":"autoComplete","multiple":false,"name":"standards.IntuneComplianceSettings.secureByDefault","label":"Mark devices with no compliance policy as","options":[{"label":"Compliant","value":"false"},{"label":"Non-Compliant","value":"true"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.IntuneComplianceSettings.secureByDefault","label":"Mark devices with no compliance policy as","options":[{"label":"Compliant","value":"false"},{"label":"Non-Compliant","value":"true"}]} {"type":"number","name":"standards.IntuneComplianceSettings.deviceComplianceCheckinThresholdDays","label":"Compliance status validity period (days)"} IMPACT Low Impact POWERSHELLEQUIVALENT - + RECOMMENDEDBY UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block @@ -33,7 +33,8 @@ function Invoke-CIPPStandardIntuneComplianceSettings { $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/deviceManagement/settings' -tenantid $Tenant if ($null -eq $Settings.deviceComplianceCheckinThresholdDays) { $Settings.deviceComplianceCheckinThresholdDays = $CurrentState.deviceComplianceCheckinThresholdDays } - $StateIsCorrect = ($CurrentState.secureByDefault -eq $Settings.secureByDefault.value) -and + $SecureByDefault = $Settings.secureByDefault.value ?? $Settings.secureByDefault + $StateIsCorrect = ($CurrentState.secureByDefault -eq $SecureByDefault) -and ($CurrentState.deviceComplianceCheckinThresholdDays -eq $Settings.deviceComplianceCheckinThresholdDays) if ($Settings.remediate -eq $true) { @@ -43,13 +44,13 @@ function Invoke-CIPPStandardIntuneComplianceSettings { try { $GraphRequest = @{ tenantID = $Tenant - uri = "https://graph.microsoft.com/beta/deviceManagement" + uri = 'https://graph.microsoft.com/beta/deviceManagement' AsApp = $true Type = 'PATCH' ContentType = 'application/json; charset=utf-8' Body = [pscustomobject]@{ settings = [pscustomobject]@{ - secureByDefault = $Settings.secureByDefault.value + secureByDefault = $SecureByDefault deviceComplianceCheckinThresholdDays = $Settings.deviceComplianceCheckinThresholdDays } } | ConvertTo-Json -Compress @@ -57,20 +58,21 @@ function Invoke-CIPPStandardIntuneComplianceSettings { New-GraphPostRequest @GraphRequest Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully updated InTune Compliance settings.' -Sev Info } catch { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to update InTune Compliance settings." -Sev Error -LogData $_ + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Failed to update InTune Compliance settings.' -Sev Error -LogData $ErrorMessage } } } if ($Settings.alert -eq $true) { if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'InTune Compliance settings is enabled.' -sev Info + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'InTune Compliance settings is enabled.' -Sev Info } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'InTune Compliance settings is not enabled.' -sev Alert + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'InTune Compliance settings is not enabled.' -Sev Alert } } if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'IntuneComplianceSettings' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant + Add-CIPPBPAField -FieldName 'IntuneComplianceSettings' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 index 68a437bd4bc4..8f816c3e5207 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 @@ -15,11 +15,11 @@ function Invoke-CIPPStandardIntuneTemplate { MULTIPLE True DISABLEDFEATURES - + IMPACT High ADDEDCOMPONENT - {"type":"autoComplete","multiple":false,"name":"TemplateList","label":"Select Intune Template","api":{"url":"/api/ListIntuneTemplates","labelField":"Displayname","valueField":"GUID","queryKey":"languages"}} + {"type":"autoComplete","multiple":false,"creatable":false,"name":"TemplateList","label":"Select Intune Template","api":{"url":"/api/ListIntuneTemplates","labelField":"Displayname","valueField":"GUID","queryKey":"languages"}} {"name":"AssignTo","label":"Who should this template be assigned to?","type":"radio","options":[{"label":"Do not assign","value":"On"},{"label":"Assign to all users","value":"allLicensedUsers"},{"label":"Assign to all devices","value":"AllDevices"},{"label":"Assign to all users and devices","value":"AllDevicesAndUsers"},{"label":"Assign to Custom Group","value":"customGroup"}]} {"type":"textField","required":false,"name":"customGroup","label":"Enter the custom group name if you selected 'Assign to Custom Group'. Wildcards are allowed."} UPDATECOMMENTBLOCK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardLegacyMFACleanup.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardLegacyMFACleanup.ps1 index 018cc262c0ef..01278dcb65db 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardLegacyMFACleanup.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardLegacyMFACleanup.ps1 @@ -28,5 +28,6 @@ function Invoke-CIPPStandardLegacyMFACleanup { param($Tenant, $Settings) Write-LogMessage -API 'Standards' -tenant $tenant -message 'Per User MFA APIs have been disabled.' -sev Info + # TODO - Re-implement this standard } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 index b00f525d0fef..55786b89ae3c 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 @@ -15,7 +15,7 @@ function Invoke-CIPPStandardNudgeMFA { TAG "lowimpact" ADDEDCOMPONENT - {"type":"select","multiple":false,"label":"Select value","name":"standards.NudgeMFA.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} + {"type":"autoComplete","multiple":false,"creatable":false,"label":"Select value","name":"standards.NudgeMFA.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} {"type":"number","name":"standards.NudgeMFA.snoozeDurationInDays","label":"Number of days to allow users to skip registering Authenticator (0-14, default is 1)","default":1} IMPACT Low Impact @@ -31,63 +31,65 @@ function Invoke-CIPPStandardNudgeMFA { param($Tenant, $Settings) ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'NudgeMFA' + # Get state value using null-coalescing operator + $state = $Settings.state.value ?? $Settings.state + $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy' -tenantid $Tenant - $StateIsCorrect = ($CurrentState.registrationEnforcement.authenticationMethodsRegistrationCampaign.state -eq $Settings.state) -and + $StateIsCorrect = ($CurrentState.registrationEnforcement.authenticationMethodsRegistrationCampaign.state -eq $state) -and ($CurrentState.registrationEnforcement.authenticationMethodsRegistrationCampaign.snoozeDurationInDays -eq $Settings.snoozeDurationInDays) -and ($CurrentState.registrationEnforcement.authenticationMethodsRegistrationCampaign.enforceRegistrationAfterAllowedSnoozes -eq $true) if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'NudgeMFA' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant + Add-CIPPBPAField -FieldName 'NudgeMFA' -FieldValue $StateIsCorrect -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 + if (([string]::IsNullOrWhiteSpace($state) -or $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 (([Int32]$Settings.snoozeDurationInDays -lt 0 -or [Int32]$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 + 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) + $StateName = $state.Substring(0, 1).ToUpper() + $state.Substring(1) if ($StatsIsCorrect -eq $false) { try { $GraphRequest = @{ - tenantid = $tenant - uri = 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy' - AsApp = $false - Type = 'PATCH' + tenantid = $Tenant + uri = 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy' + AsApp = $false + Type = 'PATCH' ContentType = 'application/json' - Body = @{ + Body = @{ registrationEnforcement = @{ authenticationMethodsRegistrationCampaign = @{ - state = $Settings.state - snoozeDurationInDays = $Settings.snoozeDurationInDays + state = $state + snoozeDurationInDays = $Settings.snoozeDurationInDays enforceRegistrationAfterAllowedSnoozes = $true } } } | ConvertTo-Json -Depth 10 -Compress } New-GraphPostRequest @GraphRequest - Write-LogMessage -API 'Standards' -tenant $tenant -message "$StateName Authenticator App Nudge with a snooze duration of $($Settings.snoozeDurationInDays)" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "$StateName Authenticator App Nudge with a snooze duration of $($Settings.snoozeDurationInDays)" -sev Info } catch { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set Authenticator App Nudge to $($Settings.state)" -sev Error -LogData $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Authenticator App Nudge to $state" -sev Error -LogData $_ } } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Authenticator App Nudge is already set to $($Settings.state) with a snooze duration of $($Settings.snoozeDurationInDays)" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Authenticator App Nudge is already set to $state with a snooze duration of $($Settings.snoozeDurationInDays)" -sev Info } } if ($Settings.alert -eq $true) { if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Authenticator App Nudge is enabled with a snooze duration of $($CurrentState.registrationEnforcement.authenticationMethodsRegistrationCampaign.snoozeDurationInDays)" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Authenticator App Nudge is enabled with a snooze duration of $($CurrentState.registrationEnforcement.authenticationMethodsRegistrationCampaign.snoozeDurationInDays)" -sev Info } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Authenticator App Nudge is not enabled with a snooze duration of $($CurrentState.registrationEnforcement.authenticationMethodsRegistrationCampaign.snoozeDurationInDays)" -sev Alert + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Authenticator App Nudge is not enabled with a snooze duration of $($CurrentState.registrationEnforcement.authenticationMethodsRegistrationCampaign.snoozeDurationInDays)" -sev Alert } } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 index 5df66cd46ca5..2bb61266853c 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 @@ -23,6 +23,7 @@ function Invoke-CIPPStandardOauthConsent { Update-MgPolicyAuthorizationPolicy RECOMMENDEDBY "CIS" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 index 4116d53897c6..a951163aaf6c 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 @@ -15,7 +15,7 @@ function Invoke-CIPPStandardPWcompanionAppAllowedState { TAG "lowimpact" ADDEDCOMPONENT - {"type":"select","multiple":false,"label":"Select value","name":"standards.PWcompanionAppAllowedState.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} + {"type":"autoComplete","multiple":false,"creatable":false,"label":"Select value","name":"standards.PWcompanionAppAllowedState.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} IMPACT Low Impact POWERSHELLEQUIVALENT @@ -30,30 +30,33 @@ function Invoke-CIPPStandardPWcompanionAppAllowedState { param($Tenant, $Settings) ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'PWcompanionAppAllowedState' - $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 } + $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 + Add-CIPPBPAField -FieldName 'companionAppAllowedState' -FieldValue $authState -StoreAs bool -Tenant $Tenant } + # Get state value using null-coalescing operator + $state = $Settings.state.value ?? $Settings.state + # 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 + if (([string]::IsNullOrWhiteSpace($state) -or $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) { - Write-LogMessage -API 'Standards' -tenant $tenant -message "companionAppAllowedState is already set to the desired state of $($Settings.state)." -sev Info + if ($authenticatorFeaturesState.featureSettings.companionAppAllowedState.state -eq $state) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "companionAppAllowedState is already set to the desired state of $state." -sev Info } else { try { # Remove number matching from featureSettings because this is now Microsoft enforced and shipping it returns an error $authenticatorFeaturesState.featureSettings.PSObject.Properties.Remove('numberMatchingRequiredState') # Define feature body $featureBody = @{ - state = $Settings.state + state = $state includeTarget = [PSCustomObject]@{ targetType = 'group' id = 'all_users' @@ -65,21 +68,21 @@ function Invoke-CIPPStandardPWcompanionAppAllowedState { } $authenticatorFeaturesState.featureSettings.companionAppAllowedState = $featureBody $body = ConvertTo-Json -Depth 3 -Compress -InputObject $authenticatorFeaturesState - (New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator' -Type patch -Body $body -ContentType 'application/json') - Write-LogMessage -API 'Standards' -tenant $tenant -message "Set companionAppAllowedState to $($Settings.state)." -sev Info + $null = (New-GraphPostRequest -tenantid $Tenant -Uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator' -Type patch -Body $body -ContentType 'application/json') + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Set companionAppAllowedState to $state." -sev Info } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set companionAppAllowedState to $($Settings.state). Error: $ErrorMessage" -sev Error + $ErrorMessage = Get-CippExceptionMessage -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set companionAppAllowedState to $state. Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage } } } if ($Settings.alert -eq $true) { - if ($authstate) { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'companionAppAllowedState is enabled.' -sev Info + if ($authState) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'companionAppAllowedState is enabled.' -sev Info } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'companionAppAllowedState is not enabled.' -sev Alert + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'companionAppAllowedState is not enabled.' -sev Alert } } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 index fd6d68613ace..1e1495edb6fb 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 @@ -23,6 +23,7 @@ function Invoke-CIPPStandardPasswordExpireDisabled { Update-MgDomain RECOMMENDEDBY "CIS" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardProfilePhotos.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardProfilePhotos.ps1 index 1c0472b3749b..6cb5c6b0bcb3 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardProfilePhotos.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardProfilePhotos.ps1 @@ -1,4 +1,4 @@ -function Invoke-CIPPStandardProfilePhotos { +function Invoke-CIPPStandardProfilePhotos { <# .FUNCTIONALITY Internal @@ -7,7 +7,7 @@ .SYNOPSIS (Label) Allow users to set profile photos .DESCRIPTION - (Helptext) Controls whether users can set their own profile photos in Microsoft 365 + (Helptext) Controls whether users can set their own profile photos in Microsoft 365. (DocsDescription) Controls whether users can set their own profile photos in Microsoft 365. When disabled, only User and Global administrators can update profile photos for users. .NOTES CAT @@ -15,25 +15,31 @@ TAG "lowimpact" ADDEDCOMPONENT - {"type":"select","multiple":false,"label":"Select value","name":"standards.ProfilePhotos.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} + {"type":"autoComplete","multiple":false,"creatable":false,"label":"Select value","name":"standards.ProfilePhotos.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} IMPACT Low Impact POWERSHELLEQUIVALENT Set-OrganizationConfig -ProfilePhotoOptions EnablePhotos and Update-MgBetaAdminPeople + RECOMMENDEDBY UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/global-standards#low-impact #> param($Tenant, $Settings) + # Get state value using null-coalescing operator + $StateValue = $Settings.state.value ?? $Settings.state + # Input validation - if ([string]::IsNullOrWhiteSpace($Settings.state)) { + if ([string]::IsNullOrWhiteSpace($StateValue)) { Write-LogMessage -API 'Standards' -tenant $tenant -message 'ProfilePhotos: Invalid state parameter set' -sev Error Return } # true if wanted state is enabled, false if disabled - $DesiredState = $Settings.state -eq 'enabled' + $DesiredState = $StateValue -eq 'enabled' <# HACK This does not work, as the API endpoint is not available via GDAP it seems? It works in the Graph Explorer, but not here. @@ -61,12 +67,12 @@ if ($CurrentStatesCorrect -eq $false) { Write-Host 'Settings are not correct' try { - if ($Settings.state -eq 'enabled') { + if ($StateValue -eq 'enabled') { Write-Host 'Enabling' # Enable photo updates $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-OwaMailboxPolicy' -cmdParams @{Identity = $CurrentOWAState.Identity; SetPhotoEnabled = $true } -useSystemMailbox $true # $null = New-GraphRequest -uri $Uri -tenant $Tenant -type DELETE - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Set Profile photo settings to $($Settings.state)" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Set Profile photo settings to $StateValue" -sev Info } else { Write-Host 'Disabling' @@ -82,23 +88,23 @@ # } # $body = ConvertTo-Json -InputObject $body -Depth 5 -Compress # $null = New-GraphPostRequest -uri $Uri -tenant $Tenant -body $body -type PATCH -AsApp $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Set Profile photo settings to $($Settings.state)" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Set Profile photo settings to $StateValue" -sev Info } } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set profile photo settings to $($Settings.state). Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set profile photo settings to $StateValue. Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage } } else { Write-Host 'Settings are correct' - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Profile photo settings are already set to the desired state: $($Settings.state)" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Profile photo settings are already set to the desired state: $StateValue" -sev Info } } if ($Settings.alert -eq $true) { if ($CurrentStatesCorrect -eq $false) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Profile photo settings do not match desired state: $($Settings.state)" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Profile photo settings do not match desired state: $StateValue" -sev Info } else { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Profile photo settings match desired state: $($Settings.state)" -sev Alert + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Profile photo settings match desired state: $StateValue" -sev Alert } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 index 47776ea2f17f..a89fd5d877b8 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 @@ -22,6 +22,7 @@ function Invoke-CIPPStandardRotateDKIM { Rotate-DkimSigningConfig RECOMMENDEDBY "CIS" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDirectSharing.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDirectSharing.ps1 index c9f44c0c8a21..bd20bff087ac 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDirectSharing.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDirectSharing.ps1 @@ -22,6 +22,7 @@ function Invoke-CIPPStandardSPDirectSharing { Set-SPOTenant -DefaultSharingLinkType Direct RECOMMENDEDBY "CIS 3.0" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisallowInfectedFiles.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisallowInfectedFiles.ps1 index 76e9a1682200..f6529c0980f4 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisallowInfectedFiles.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisallowInfectedFiles.ps1 @@ -22,6 +22,7 @@ function Invoke-CIPPStandardSPDisallowInfectedFiles { Set-SPOTenant -DisallowInfectedFileDownload \$true RECOMMENDEDBY "CIS 3.0" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPEmailAttestation.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPEmailAttestation.ps1 index 05b078a5e62e..395bdd3ee208 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPEmailAttestation.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPEmailAttestation.ps1 @@ -5,10 +5,10 @@ function Invoke-CIPPStandardSPEmailAttestation { .COMPONENT (APIName) SPEmailAttestation .SYNOPSIS - (Label) Require reauthentication with verification code + (Label) Require re-authentication with verification code .DESCRIPTION - (Helptext) Ensure reauthentication with verification code is restricted - (DocsDescription) Ensure reauthentication with verification code is restricted + (Helptext) Ensure re-authentication with verification code is restricted + (DocsDescription) Ensure re-authentication with verification code is restricted .NOTES CAT SharePoint Standards @@ -16,13 +16,14 @@ function Invoke-CIPPStandardSPEmailAttestation { "mediumimpact" "CIS" ADDEDCOMPONENT - {"type":"number","name":"standards.SPEmailAttestation.Days","label":"Require reauth every X Days (Default 15)"} + {"type":"number","name":"standards.SPEmailAttestation.Days","label":"Require re-authentication every X Days (Default 15)"} IMPACT Medium Impact POWERSHELLEQUIVALENT Set-SPOTenant -EmailAttestationRequired \$true -EmailAttestationReAuthDays 15 RECOMMENDEDBY "CIS 3.0" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 index 02589cf0c61e..8e07f8e0ff24 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 @@ -33,14 +33,14 @@ function Invoke-CIPPStandardSPExternalUserExpiration { ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SPExternalUserExpiration' $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | - Select-Object -Property ExternalUserExpireInDays, ExternalUserExpirationRequired + Select-Object -Property ExternalUserExpireInDays, ExternalUserExpirationRequired $StateIsCorrect = ($CurrentState.ExternalUserExpireInDays -eq $Settings.Days) -and ($CurrentState.ExternalUserExpirationRequired -eq $true) if ($Settings.remediate -eq $true) { if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Sharepoint External User Expiration is already enabled.' -Sev Info + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint External User Expiration is already enabled.' -Sev Info } else { $Properties = @{ ExternalUserExpireInDays = $Settings.Days @@ -51,8 +51,8 @@ function Invoke-CIPPStandardSPExternalUserExpiration { Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully set External User Expiration' -Sev Info } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to set External User Expiration. Error: $ErrorMessage" -Sev Error + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to set External User Expiration. Error: $($ErrorMessage.NormalizedError)" -Sev Error -LogData $ErrorMessage } } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPSyncButtonState.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPSyncButtonState.ps1 index 4b54a8b44ad3..c3da574978b3 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPSyncButtonState.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPSyncButtonState.ps1 @@ -15,7 +15,7 @@ function Invoke-CIPPStandardSPSyncButtonState { TAG "mediumimpact" ADDEDCOMPONENT - {"type":"autoComplete","multiple":false,"label":"SharePoint Sync Button state","name":"standards.SPSyncButtonState.state","options":[{"label":"Disabled","value":"true"},{"label":"Enabled","value":"false"}]} + {"type":"autoComplete","multiple":false,"creatable":false,"label":"SharePoint Sync Button state","name":"standards.SPSyncButtonState.state","options":[{"label":"Disabled","value":"true"},{"label":"Enabled","value":"false"}]} IMPACT Medium Impact POWERSHELLEQUIVALENT @@ -31,20 +31,22 @@ function Invoke-CIPPStandardSPSyncButtonState { ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SPSyncButtonState' $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | Select-Object _ObjectIdentity_, TenantFilter, HideSyncButtonOnDocLib - $WantedState = [System.Convert]::ToBoolean($Settings.state) - $StateIsCorrect = if ($CurrentState.HideSyncButtonOnDocLib -eq $WantedState) { $true } else { $false } - $HumanReadableState = if ($WantedState -eq $true) { 'disabled' } else { 'enabled' } if ($Settings.report -eq $true) { Add-CIPPBPAField -FieldName 'SPSyncButtonDisabled' -FieldValue $CurrentState.HideSyncButtonOnDocLib -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)) { + $StateValue = $Settings.state.value ?? $Settings.state + if (([string]::IsNullOrWhiteSpace($StateValue) -or $StateValue -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { Write-LogMessage -API 'Standards' -tenant $tenant -message 'SPSyncButtonState: Invalid state parameter set' -sev Error Return } + $WantedState = [System.Convert]::ToBoolean($StateValue) + $StateIsCorrect = if ($CurrentState.HideSyncButtonOnDocLib -eq $WantedState) { $true } else { $false } + $HumanReadableState = if ($WantedState -eq $true) { 'disabled' } else { 'enabled' } + if ($Settings.remediate -eq $true) { Write-Host 'Time to remediate' diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 index d45abf7e5973..4f6dda4c235d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 @@ -19,7 +19,7 @@ function Invoke-CIPPStandardSafeAttachmentPolicy { "mdo_commonattachmentsfilter" "mdo_safeattachmentpolicy" ADDEDCOMPONENT - {"type":"select","multiple":false,"label":"Action","name":"standards.SafeAttachmentPolicy.Action","options":[{"label":"Allow","value":"Allow"},{"label":"Block","value":"Block"},{"label":"DynamicDelivery","value":"DynamicDelivery"}]} + {"type":"select","multiple":false,"label":"Safe Attachment Action","name":"standards.SafeAttachmentPolicy.SafeAttachmentAction","options":[{"label":"Allow","value":"Allow"},{"label":"Block","value":"Block"},{"label":"DynamicDelivery","value":"DynamicDelivery"}]} {"type":"select","multiple":false,"label":"QuarantineTag","name":"standards.SafeAttachmentPolicy.QuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} {"type":"switch","label":"Redirect","name":"standards.SafeAttachmentPolicy.Redirect"} {"type":"textField","name":"standards.SafeAttachmentPolicy.RedirectAddress","label":"Redirect Address","required":false} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 index 283bc4d5a267..7d67aa1471fe 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 @@ -22,6 +22,7 @@ function Invoke-CIPPStandardSafeSendersDisable { POWERSHELLEQUIVALENT Set-MailboxJunkEmailConfiguration RECOMMENDEDBY + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 index 4084650d240e..b6b8eae02516 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 @@ -20,6 +20,7 @@ function Invoke-CIPPStandardSendFromAlias { POWERSHELLEQUIVALENT Set-Mailbox RECOMMENDEDBY + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 index c1469596a27e..7204975387ad 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 @@ -15,7 +15,7 @@ function Invoke-CIPPStandardShortenMeetings { TAG "mediumimpact" ADDEDCOMPONENT - {"type":"select","multiple":false,"label":"Select value","name":"standards.ShortenMeetings.ShortenEventScopeDefault","options":[{"label":"Disabled/None","value":"None"},{"label":"End early","value":"EndEarly"},{"label":"Start late","value":"StartLate"}]} + {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.ShortenMeetings.ShortenEventScopeDefault","options":[{"label":"Disabled/None","value":"None"},{"label":"End early","value":"EndEarly"},{"label":"Start late","value":"StartLate"}]} {"type":"number","name":"standards.ShortenMeetings.DefaultMinutesToReduceShortEventsBy","label":"Minutes to reduce short calendar events by (Default is 5)","default":5} {"type":"number","name":"standards.ShortenMeetings.DefaultMinutesToReduceLongEventsBy","label":"Minutes to reduce long calendar events by (Default is 10)","default":10} IMPACT @@ -34,17 +34,20 @@ 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 + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'ShortenMeetings: Invalid setting specified. DefaultMinutesToReduceShortEventsBy must be an integer between 0 and 29' -sev Error 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 + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'ShortenMeetings: Invalid setting specified. DefaultMinutesToReduceLongEventsBy must be an integer between 0 and 29' -sev Error Return } + # Get state value using null-coalescing operator + $scopeDefault = $Settings.ShortenEventScopeDefault.value ?? $Settings.ShortenEventScopeDefault + $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig' | - Select-Object -Property ShortenEventScopeDefault, DefaultMinutesToReduceShortEventsBy, DefaultMinutesToReduceLongEventsBy - $CorrectState = if ($CurrentState.ShortenEventScopeDefault -eq $Settings.ShortenEventScopeDefault -and + Select-Object -Property ShortenEventScopeDefault, DefaultMinutesToReduceShortEventsBy, DefaultMinutesToReduceLongEventsBy + $CorrectState = if ($CurrentState.ShortenEventScopeDefault -eq $scopeDefault -and $CurrentState.DefaultMinutesToReduceShortEventsBy -eq $Settings.DefaultMinutesToReduceShortEventsBy -and $CurrentState.DefaultMinutesToReduceLongEventsBy -eq $Settings.DefaultMinutesToReduceLongEventsBy) { $true } else { $false } @@ -52,14 +55,14 @@ function Invoke-CIPPStandardShortenMeetings { Write-Host 'Time to remediate' if ($CorrectState -eq $true) { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'Shorten meetings settings are already in the correct state. ' -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Shorten meetings settings are already in the correct state. ' -sev Info } else { try { - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdParams @{ShortenEventScopeDefault = $Settings.ShortenEventScopeDefault; DefaultMinutesToReduceShortEventsBy = $Settings.DefaultMinutesToReduceShortEventsBy; DefaultMinutesToReduceLongEventsBy = $Settings.DefaultMinutesToReduceLongEventsBy } - Write-LogMessage -API 'Standards' -tenant $tenant -message "Shorten meetings settings have been set to the following state. State: $($Settings.ShortenEventScopeDefault), Short:$($Settings.DefaultMinutesToReduceShortEventsBy), Long: $($Settings.DefaultMinutesToReduceLongEventsBy)" -sev Info + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdParams @{ShortenEventScopeDefault = $Settings.ShortenEventScopeDefault; DefaultMinutesToReduceShortEventsBy = $Settings.DefaultMinutesToReduceShortEventsBy; DefaultMinutesToReduceLongEventsBy = $Settings.DefaultMinutesToReduceLongEventsBy } + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Shorten meetings settings have been set to the following state. State: $($Settings.ShortenEventScopeDefault), Short:$($Settings.DefaultMinutesToReduceShortEventsBy), Long: $($Settings.DefaultMinutesToReduceLongEventsBy)" -sev Info } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set shorten meetings settings. Error: $ErrorMessage" -sev Error + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set shorten meetings settings. Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage } } } @@ -67,18 +70,18 @@ function Invoke-CIPPStandardShortenMeetings { if ($Settings.alert -eq $true) { if ($CorrectState -eq $true) { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Shorten meetings settings are already in the correct state. Current state: $($CurrentState.ShortenEventScopeDefault), Short:$($CurrentState.DefaultMinutesToReduceShortEventsBy), Long: $($CurrentState.DefaultMinutesToReduceLongEventsBy)" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Shorten meetings settings are already in the correct state. Current state: $($CurrentState.ShortenEventScopeDefault), Short:$($CurrentState.DefaultMinutesToReduceShortEventsBy), Long: $($CurrentState.DefaultMinutesToReduceLongEventsBy)" -sev Info } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Shorten meetings settings are not in the correct state. Current state: $($CurrentState.ShortenEventScopeDefault), Short:$($CurrentState.DefaultMinutesToReduceShortEventsBy), Long: $($CurrentState.DefaultMinutesToReduceLongEventsBy)" -sev Alert + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Shorten meetings settings are not in the correct state. Current state: $($CurrentState.ShortenEventScopeDefault), Short:$($CurrentState.DefaultMinutesToReduceShortEventsBy), Long: $($CurrentState.DefaultMinutesToReduceLongEventsBy)" -sev Alert } } if ($Settings.report -eq $true) { if ($CorrectState -eq $true) { - Add-CIPPBPAField -FieldName 'ShortenMeetings' -FieldValue $CorrectState -StoreAs bool -Tenant $tenant + Add-CIPPBPAField -FieldName 'ShortenMeetings' -FieldValue $CorrectState -StoreAs bool -Tenant $Tenant } else { - Add-CIPPBPAField -FieldName 'ShortenMeetings' -FieldValue $CurrentState -StoreAs json -Tenant $tenant + Add-CIPPBPAField -FieldName 'ShortenMeetings' -FieldValue $CurrentState -StoreAs json -Tenant $Tenant } } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 index 0a1a86939f08..539024fd842f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 @@ -16,15 +16,15 @@ function Invoke-CIPPStandardSpamFilterPolicy { "mediumimpact" ADDEDCOMPONENT {"type":"number","label":"Bulk email threshold (Default 7)","name":"standards.SpamFilterPolicy.BulkThreshold","default":7} - {"type":"autoComplete","multiple":false,"label":"Spam Action","name":"standards.SpamFilterPolicy.SpamAction","options":[{"label":"Quarantine the message","value":"Quarantine"},{"label":"Move message to Junk Email folder","value":"MoveToJmf"}]} - {"type":"autoComplete","multiple":false,"label":"Spam Quarantine Tag","name":"standards.SpamFilterPolicy.SpamQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} - {"type":"autoComplete","multiple":false,"label":"High Confidence Spam Action","name":"standards.SpamFilterPolicy.HighConfidenceSpamAction","options":[{"label":"Quarantine the message","value":"Quarantine"},{"label":"Move message to Junk Email folder","value":"MoveToJmf"}]} - {"type":"autoComplete","multiple":false,"label":"High Confidence Spam Quarantine Tag","name":"standards.SpamFilterPolicy.HighConfidenceSpamQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} - {"type":"autoComplete","multiple":false,"label":"Bulk Spam Action","name":"standards.SpamFilterPolicy.BulkSpamAction","options":[{"label":"Quarantine the message","value":"Quarantine"},{"label":"Move message to Junk Email folder","value":"MoveToJmf"}]} - {"type":"autoComplete","multiple":false,"label":"Bulk Quarantine Tag","name":"standards.SpamFilterPolicy.BulkQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} - {"type":"autoComplete","multiple":false,"label":"Phish Spam Action","name":"standards.SpamFilterPolicy.PhishSpamAction","options":[{"label":"Quarantine the message","value":"Quarantine"},{"label":"Move message to Junk Email folder","value":"MoveToJmf"}]} - {"type":"autoComplete","multiple":false,"label":"Phish Quarantine Tag","name":"standards.SpamFilterPolicy.PhishQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} - {"type":"autoComplete","multiple":false,"label":"High Confidence Phish Quarantine Tag","name":"standards.SpamFilterPolicy.HighConfidencePhishQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Spam Action","name":"standards.SpamFilterPolicy.SpamAction","options":[{"label":"Quarantine the message","value":"Quarantine"},{"label":"Move message to Junk Email folder","value":"MoveToJmf"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Spam Quarantine Tag","name":"standards.SpamFilterPolicy.SpamQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"High Confidence Spam Action","name":"standards.SpamFilterPolicy.HighConfidenceSpamAction","options":[{"label":"Quarantine the message","value":"Quarantine"},{"label":"Move message to Junk Email folder","value":"MoveToJmf"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"High Confidence Spam Quarantine Tag","name":"standards.SpamFilterPolicy.HighConfidenceSpamQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Bulk Spam Action","name":"standards.SpamFilterPolicy.BulkSpamAction","options":[{"label":"Quarantine the message","value":"Quarantine"},{"label":"Move message to Junk Email folder","value":"MoveToJmf"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Bulk Quarantine Tag","name":"standards.SpamFilterPolicy.BulkQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Phish Spam Action","name":"standards.SpamFilterPolicy.PhishSpamAction","options":[{"label":"Quarantine the message","value":"Quarantine"},{"label":"Move message to Junk Email folder","value":"MoveToJmf"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Phish Quarantine Tag","name":"standards.SpamFilterPolicy.PhishQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"High Confidence Phish Quarantine Tag","name":"standards.SpamFilterPolicy.HighConfidencePhishQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} IMPACT Medium Impact POWERSHELLEQUIVALENT @@ -45,17 +45,27 @@ function Invoke-CIPPStandardSpamFilterPolicy { Where-Object -Property Name -EQ $PolicyName | Select-Object -Property * + $SpamAction = $Settings.SpamAction.value ?? $Settings.SpamAction + $SpamQuarantineTag = $Settings.SpamQuarantineTag.value ?? $Settings.SpamQuarantineTag + $HighConfidenceSpamAction = $Settings.HighConfidenceSpamAction.value ?? $Settings.HighConfidenceSpamAction + $HighConfidenceSpamQuarantineTag = $Settings.HighConfidenceSpamQuarantineTag.value ?? $Settings.HighConfidenceSpamQuarantineTag + $BulkSpamAction = $Settings.BulkSpamAction.value ?? $Settings.BulkSpamAction + $BulkQuarantineTag = $Settings.BulkQuarantineTag.value ?? $Settings.BulkQuarantineTag + $PhishSpamAction = $Settings.PhishSpamAction.value ?? $Settings.PhishSpamAction + $PhishQuarantineTag = $Settings.PhishQuarantineTag.value ?? $Settings.PhishQuarantineTag + $HighConfidencePhishQuarantineTag = $Settings.HighConfidencePhishQuarantineTag.value ?? $Settings.HighConfidencePhishQuarantineTag + $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and - ($CurrentState.SpamAction -eq $Settings.SpamAction.value) -and - ($CurrentState.SpamQuarantineTag -eq $Settings.SpamQuarantineTag.value) -and - ($CurrentState.HighConfidenceSpamAction -eq $Settings.HighConfidenceSpamAction.value) -and - ($CurrentState.HighConfidenceSpamQuarantineTag -eq $Settings.HighConfidenceSpamQuarantineTag.value) -and - ($CurrentState.BulkSpamAction -eq $Settings.BulkSpamAction.value) -and - ($CurrentState.BulkQuarantineTag -eq $Settings.BulkQuarantineTag.value) -and - ($CurrentState.PhishSpamAction -eq $Settings.PhishSpamAction.value) -and - ($CurrentState.PhishQuarantineTag -eq $Settings.PhishQuarantineTag.value) -and + ($CurrentState.SpamAction -eq $SpamAction) -and + ($CurrentState.SpamQuarantineTag -eq $SpamQuarantineTag) -and + ($CurrentState.HighConfidenceSpamAction -eq $HighConfidenceSpamAction) -and + ($CurrentState.HighConfidenceSpamQuarantineTag -eq $HighConfidenceSpamQuarantineTag) -and + ($CurrentState.BulkSpamAction -eq $BulkSpamAction) -and + ($CurrentState.BulkQuarantineTag -eq $BulkQuarantineTag) -and + ($CurrentState.PhishSpamAction -eq $PhishSpamAction) -and + ($CurrentState.PhishQuarantineTag -eq $PhishQuarantineTag) -and ($CurrentState.HighConfidencePhishAction -eq 'Quarantine') -and - ($CurrentState.HighConfidencePhishQuarantineTag -eq $Settings.HighConfidencePhishQuarantineTag.value) -and + ($CurrentState.HighConfidencePhishQuarantineTag -eq $HighConfidencePhishQuarantineTag) -and ($CurrentState.BulkThreshold -eq $Settings.BulkThreshold) -and ($CurrentState.QuarantineRetentionPeriod -eq 30) -and ($CurrentState.IncreaseScoreWithNumericIps -eq 'On') -and @@ -86,16 +96,16 @@ function Invoke-CIPPStandardSpamFilterPolicy { Write-LogMessage -API 'Standards' -Tenant $Tenant -message 'Spam Filter Policy already correctly configured' -sev Info } else { $cmdparams = @{ - SpamAction = $Settings.SpamAction.value - SpamQuarantineTag = $Settings.SpamQuarantineTag.value - HighConfidenceSpamAction = $Settings.HighConfidenceSpamAction.value - HighConfidenceSpamQuarantineTag = $Settings.HighConfidenceSpamQuarantineTag.value - BulkSpamAction = $Settings.BulkSpamAction.value - BulkQuarantineTag = $Settings.BulkQuarantineTag.value - PhishSpamAction = $Settings.PhishSpamAction.value - PhishQuarantineTag = $Settings.PhishQuarantineTag.value + SpamAction = $SpamAction + SpamQuarantineTag = $SpamQuarantineTag + HighConfidenceSpamAction = $HighConfidenceSpamAction + HighConfidenceSpamQuarantineTag = $HighConfidenceSpamQuarantineTag + BulkSpamAction = $BulkSpamAction + BulkQuarantineTag = $BulkQuarantineTag + PhishSpamAction = $PhishSpamAction + PhishQuarantineTag = $PhishQuarantineTag HighConfidencePhishAction = 'Quarantine' - HighConfidencePhishQuarantineTag = $Settings.HighConfidencePhishQuarantineTag.value + HighConfidencePhishQuarantineTag = $HighConfidencePhishQuarantineTag BulkThreshold = $Settings.BulkThreshold QuarantineRetentionPeriod = 30 IncreaseScoreWithNumericIps = 'On' @@ -110,21 +120,21 @@ function Invoke-CIPPStandardSpamFilterPolicy { PhishZapEnabled = $true SpamZapEnabled = $true } - Write-Host "================== DEBUG ==================" - Write-Host $cmdparams + Write-Host '================== DEBUG ==================' + Write-Host $cmdParams if ($CurrentState.Name -eq $PolicyName) { try { - $cmdparams.Add('Identity', $PolicyName) - New-ExoRequest -TenantId $Tenant -cmdlet 'Set-HostedContentFilterPolicy' -cmdparams $cmdparams -UseSystemMailbox $true + $cmdParams.Add('Identity', $PolicyName) + $null = New-ExoRequest -TenantId $Tenant -cmdlet 'Set-HostedContentFilterPolicy' -cmdParams $cmdParams -UseSystemMailbox $true Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Updated Spam Filter policy $PolicyName." -sev Info } catch { Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Failed to update Spam Filter policy $PolicyName." -sev Error -LogData $_ } } else { try { - $cmdparams.Add('Name', $PolicyName) - New-ExoRequest -TenantId $Tenant -cmdlet 'New-HostedContentFilterPolicy' -cmdparams $cmdparams -UseSystemMailbox $true + $cmdParams.Add('Name', $PolicyName) + $null = New-ExoRequest -TenantId $Tenant -cmdlet 'New-HostedContentFilterPolicy' -cmdParams $cmdParams -UseSystemMailbox $true Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Created Spam Filter policy $PolicyName." -sev Info } catch { Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Failed to create Spam Filter policy $PolicyName." -sev Error -LogData $_ @@ -133,27 +143,27 @@ function Invoke-CIPPStandardSpamFilterPolicy { } if ($RuleStateIsCorrect -eq $false) { - $cmdparams = @{ - Priority = 0 - RecipientDomainIs = $AcceptedDomains.Name + $cmdParams = @{ + Priority = 0 + RecipientDomainIs = $AcceptedDomains.Name } if ($RuleState.HostedContentFilterPolicy -ne $PolicyName) { - $cmdparams.Add('HostedContentFilterPolicy', $PolicyName) + $cmdParams.Add('HostedContentFilterPolicy', $PolicyName) } if ($RuleState.Name -eq $PolicyName) { try { - $cmdparams.Add('Identity', "$PolicyName") - New-ExoRequest -TenantId $Tenant -cmdlet 'Set-HostedContentFilterRule' -cmdparams $cmdparams -UseSystemMailbox $true + $cmdParams.Add('Identity', "$PolicyName") + $null = New-ExoRequest -TenantId $Tenant -cmdlet 'Set-HostedContentFilterRule' -cmdParams $cmdParams -UseSystemMailbox $true Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Updated Spam Filter rule $PolicyName." -sev Info } catch { Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Failed to update Spam Filter rule $PolicyName." -sev Error -LogData $_ } } else { try { - $cmdparams.Add('Name', "$PolicyName") - New-ExoRequest -TenantId $Tenant -cmdlet 'New-HostedContentFilterRule' -cmdparams $cmdparams -UseSystemMailbox $true + $cmdParams.Add('Name', "$PolicyName") + $null = New-ExoRequest -TenantId $Tenant -cmdlet 'New-HostedContentFilterRule' -cmdParams $cmdParams -UseSystemMailbox $true Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Created Spam Filter rule $PolicyName." -sev Info } catch { Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Failed to create Spam Filter rule $PolicyName." -sev Error -LogData $_ @@ -172,7 +182,7 @@ function Invoke-CIPPStandardSpamFilterPolicy { } if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'SpamFilterPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant + Add-CIPPBPAField -FieldName 'SpamFilterPolicy' -FieldValue $StateIsCorrect -StoreAs [bool] -Tenant $Tenant } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 index a9ba02025ac7..167cc6a3d1b1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 @@ -16,13 +16,14 @@ function Invoke-CIPPStandardSpoofWarn { "lowimpact" "CIS" ADDEDCOMPONENT - {"type":"select","multiple":false,"label":"Select value","name":"standards.SpoofWarn.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} + {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.SpoofWarn.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} IMPACT Low Impact POWERSHELLEQUIVALENT - et-ExternalInOutlook –Enabled \$true or \$false + Set-ExternalInOutlook –Enabled \$true or \$false RECOMMENDEDBY "CIS" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK @@ -35,40 +36,43 @@ function Invoke-CIPPStandardSpoofWarn { $CurrentInfo = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-ExternalInOutlook') if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'SpoofingWarnings' -FieldValue $CurrentInfo.Enabled -StoreAs bool -Tenant $tenant + Add-CIPPBPAField -FieldName 'SpoofingWarnings' -FieldValue $CurrentInfo.Enabled -StoreAs bool -Tenant $Tenant } + # Get state value using null-coalescing operator + $state = $Settings.state.value ?? $Settings.state + # 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 + if (([string]::IsNullOrWhiteSpace($state) -or $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 + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'You cannot both enable and disable the Spoof Warnings setting' -sev Error Return - } elseif ($Settings.state -eq 'enabled' -or $Settings.enable) { $true } else { $false } + } elseif ($state -eq 'enabled' -or $Settings.enable) { $true } else { $false } if ($CurrentInfo.Enabled -eq $status) { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Outlook external spoof warnings are already set to $status." -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Outlook external spoof warnings are already set to $status." -sev Info } else { try { - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-ExternalInOutlook' -cmdParams @{ Enabled = $status; } - Write-LogMessage -API 'Standards' -tenant $tenant -message "Outlook external spoof warnings set to $status." -sev Info + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-ExternalInOutlook' -cmdParams @{ Enabled = $status; } + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Outlook external spoof warnings set to $status." -sev Info } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Could not set Outlook external spoof warnings to $status. Error: $ErrorMessage" -sev Error + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Could not set Outlook external spoof warnings to $status. Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage } } } if ($Settings.alert -eq $true) { if ($CurrentInfo.Enabled -eq $true) { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'Outlook external spoof warnings are enabled.' -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Outlook external spoof warnings are enabled.' -sev Info } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'Outlook external spoof warnings are not enabled.' -sev Alert + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Outlook external spoof warnings are not enabled.' -sev Alert } } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 index fbb236903975..7d0faafb3cf1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 @@ -1,4 +1,4 @@ -function Invoke-CIPPStandardStaleEntraDevices { +function Invoke-CIPPStandardStaleEntraDevices { <# .FUNCTIONALITY Internal @@ -18,7 +18,7 @@ ADDEDCOMPONENT {"type":"number","name":"standards.StaleEntraDevices.deviceAgeThreshold","label":"Days before stale(Dont set below 30)"} DISABLEDFEATURES - + IMPACT High Impact POWERSHELLEQUIVALENT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTAP.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTAP.ps1 index 23f6ae97a643..3ec0236edce4 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTAP.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTAP.ps1 @@ -15,12 +15,13 @@ function Invoke-CIPPStandardTAP { TAG "lowimpact" ADDEDCOMPONENT - {"type":"select","multiple":false,"label":"Select TAP Lifetime","name":"standards.TAP.config","options":[{"label":"Only Once","value":"true"},{"label":"Multiple Logons","value":"false"}]} + {"type":"autoComplete","multiple":false,"creatable":false,"label":"Select TAP Lifetime","name":"standards.TAP.config","options":[{"label":"Only Once","value":"true"},{"label":"Multiple Logons","value":"false"}]} IMPACT Low Impact POWERSHELLEQUIVALENT Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration RECOMMENDEDBY + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK @@ -31,20 +32,24 @@ function Invoke-CIPPStandardTAP { ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TAP' $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authenticationmethodspolicy/authenticationMethodConfigurations/TemporaryAccessPass' -tenantid $Tenant - if ($null -eq $Settings.config) { $Settings.config = $True } + + # Get config value using null-coalescing operator + $config = $Settings.config.value ?? $Settings.config + if ($null -eq $config) { $config = $True } + $StateIsCorrect = ($CurrentState.state -eq 'enabled') -and - ([System.Convert]::ToBoolean($CurrentState.isUsableOnce) -eq [System.Convert]::ToBoolean($Settings.config)) + ([System.Convert]::ToBoolean($CurrentState.isUsableOnce) -eq [System.Convert]::ToBoolean($config)) if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'TemporaryAccessPass' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant + Add-CIPPBPAField -FieldName 'TemporaryAccessPass' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant } If ($Settings.remediate -eq $true) { if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'Temporary Access Passwords is already enabled.' -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Temporary Access Passwords is already enabled.' -sev Info } else { try { - Set-CIPPAuthenticationPolicy -Tenant $tenant -APIName 'Standards' -AuthenticationMethodId 'TemporaryAccessPass' -Enabled $true -TAPisUsableOnce $Settings.config + Set-CIPPAuthenticationPolicy -Tenant $Tenant -APIName 'Standards' -AuthenticationMethodId 'TemporaryAccessPass' -Enabled $true -TAPisUsableOnce $config } catch { } } @@ -52,9 +57,9 @@ function Invoke-CIPPStandardTAP { if ($Settings.alert -eq $true) { if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'Temporary Access Passwords is enabled.' -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Temporary Access Passwords is enabled.' -sev Info } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'Temporary Access Passwords is not enabled.' -sev Alert + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Temporary Access Passwords is not enabled.' -sev Alert } } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEnrollUser.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEnrollUser.ps1 index 464324ff4b61..7d8677312a95 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEnrollUser.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEnrollUser.ps1 @@ -15,7 +15,7 @@ Function Invoke-CIPPStandardTeamsEnrollUser { TAG "lowimpact" ADDEDCOMPONENT - {"type":"autoComplete","name":"standards.TeamsEnrollUser.EnrollUserOverride","label":"Voice and Face Enrollment","options":[{"label":"Disabled","value":"Disabled"},{"label":"Enabled","value":"Enabled"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.TeamsEnrollUser.EnrollUserOverride","label":"Voice and Face Enrollment","options":[{"label":"Disabled","value":"Disabled"},{"label":"Enabled","value":"Enabled"}]} IMPACT Low Impact POWERSHELLEQUIVALENT @@ -29,26 +29,29 @@ Function Invoke-CIPPStandardTeamsEnrollUser { param($Tenant, $Settings) - $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsMeetingPolicy' -CmdParams @{Identity = 'Global' } + # Get EnrollUserOverride value using null-coalescing operator + $enrollUserOverride = $Settings.EnrollUserOverride.value ?? $Settings.EnrollUserOverride + + $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsMeetingPolicy' -cmdParams @{Identity = 'Global' } | Select-Object EnrollUserOverride - $StateIsCorrect = ($CurrentState.EnrollUserOverride -eq $Settings.EnrollUserOverride.value) + $StateIsCorrect = ($CurrentState.EnrollUserOverride -eq $enrollUserOverride) if ($Settings.remediate -eq $true) { if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Teams Enroll User Override settings already set to $($Settings.EnrollUserOverride.value)." -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Teams Enroll User Override settings already set to $enrollUserOverride." -sev Info } else { - $cmdparams = @{ + $cmdParams = @{ Identity = 'Global' - EnrollUserOverride = $Settings.EnrollUserOverride.value + EnrollUserOverride = $enrollUserOverride } try { - New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTeamsMeetingPolicy' -CmdParams $cmdparams - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Teams Enroll User Override setting to $($Settings.EnrollUserOverride.value)." -sev Info + $null = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTeamsMeetingPolicy' -cmdParams $cmdParams + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Teams Enroll User Override setting to $enrollUserOverride." -sev Info } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Teams Enroll User Override setting to $($Settings.EnrollUserOverride.value)." -sev Error -LogData $ErrorMessage + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Teams Enroll User Override setting to $enrollUserOverride." -sev Error -LogData $ErrorMessage } } } @@ -61,7 +64,7 @@ Function Invoke-CIPPStandardTeamsEnrollUser { } } - if ($Setings.report -eq $true) { + if ($Settings.report -eq $true) { Add-CIPPBPAField -FieldName 'TeamsEnrollUser' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 index aea9e7a3e6b0..8d1c8d84270d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 @@ -17,7 +17,7 @@ Function Invoke-CIPPStandardTeamsFederationConfiguration { ADDEDCOMPONENT {"type":"switch","name":"standards.TeamsFederationConfiguration.AllowTeamsConsumer","label":"Allow users to communicate with other organizations"} {"type":"switch","name":"standards.TeamsFederationConfiguration.AllowPublicUsers","label":"Allow users to communicate with Skype Users"} - {"type":"autoComplete","multiple":false,"name":"standards.TeamsFederationConfiguration.DomainControl","label":"Communication Mode","options":[{"label":"Allow all external domains","value":"AllowAllExternal"},{"label":"Block all external domains","value":"BlockAllExternal"},{"label":"Allow specific external domains","value":"AllowSpecificExternal"},{"label":"Block specific external domains","value":"BlockSpecificExternal"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.TeamsFederationConfiguration.DomainControl","label":"Communication Mode","options":[{"label":"Allow all external domains","value":"AllowAllExternal"},{"label":"Block all external domains","value":"BlockAllExternal"},{"label":"Allow specific external domains","value":"AllowSpecificExternal"},{"label":"Block specific external domains","value":"BlockSpecificExternal"}]} {"type":"textField","name":"standards.TeamsFederationConfiguration.DomainList","label":"Domains, Comma separated","required":false} IMPACT Medium Impact @@ -36,7 +36,8 @@ Function Invoke-CIPPStandardTeamsFederationConfiguration { $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTenantFederationConfiguration' -CmdParams @{Identity = 'Global' } | Select-Object * - Switch ($Settings.DomainControl.value) { + $DomainControl = $Settings.DomainControl.value ?? $Settings.DomainControl + Switch ($DomainControl) { 'AllowAllExternal' { $AllowFederatedUsers = $true $AllowedDomainsAsAList = 'AllowAllKnownDomains' @@ -66,7 +67,7 @@ Function Invoke-CIPPStandardTeamsFederationConfiguration { } } Default { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Federation Configuration: Invalid $($Settings.DomainControl.value) parameter" -sev Error + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Federation Configuration: Invalid $DomainControl parameter" -sev Error Return } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 index 4d0cfd8ff359..6ea500719d57 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 @@ -15,9 +15,9 @@ Function Invoke-CIPPStandardTeamsGlobalMeetingPolicy { TAG "lowimpact" ADDEDCOMPONENT - {"type":"autoComplete","multiple":false,"name":"standards.TeamsGlobalMeetingPolicy.DesignatedPresenterRoleMode","label":"Default value of the `Who can present?`","options":[{"label":"EveryoneUserOverride","value":"EveryoneUserOverride"},{"label":"EveryoneInCompanyUserOverride","value":"EveryoneInCompanyUserOverride"},{"label":"EveryoneInSameAndFederatedCompanyUserOverride","value":"EveryoneInSameAndFederatedCompanyUserOverride"},{"label":"OrganizerOnlyUserOverride","value":"OrganizerOnlyUserOverride"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.TeamsGlobalMeetingPolicy.DesignatedPresenterRoleMode","label":"Default value of the `Who can present?`","options":[{"label":"EveryoneUserOverride","value":"EveryoneUserOverride"},{"label":"EveryoneInCompanyUserOverride","value":"EveryoneInCompanyUserOverride"},{"label":"EveryoneInSameAndFederatedCompanyUserOverride","value":"EveryoneInSameAndFederatedCompanyUserOverride"},{"label":"OrganizerOnlyUserOverride","value":"OrganizerOnlyUserOverride"}]} {"type":"switch","name":"standards.TeamsGlobalMeetingPolicy.AllowAnonymousUsersToJoinMeeting","label":"Allow anonymous users to join meeting"} - {"type":"autoComplete","multiple":false,"name":"standards.TeamsGlobalMeetingPolicy.MeetingChatEnabledType","label":"Meeting chat policy","options":[{"label":"On for everyone","value":"Enabled"},{"label":"On for everyone but anonymous users","value":"EnabledExceptAnonymous"},{"label":"Off for everyone","value":"Disabled"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.TeamsGlobalMeetingPolicy.MeetingChatEnabledType","label":"Meeting chat policy","options":[{"label":"On for everyone","value":"Enabled"},{"label":"On for everyone but anonymous users","value":"EnabledExceptAnonymous"},{"label":"Off for everyone","value":"Disabled"}]} IMPACT Low Impact POWERSHELLEQUIVALENT @@ -35,35 +35,38 @@ Function Invoke-CIPPStandardTeamsGlobalMeetingPolicy { $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsMeetingPolicy' -CmdParams @{Identity = 'Global' } | Select-Object AllowAnonymousUsersToJoinMeeting, AllowAnonymousUsersToStartMeeting, AutoAdmittedUsers, AllowPSTNUsersToBypassLobby, MeetingChatEnabledType, DesignatedPresenterRoleMode, AllowExternalParticipantGiveRequestControl + $MeetingChatEnabledType = $Settings.MeetingChatEnabledType.value ?? $Settings.MeetingChatEnabledType + $DesignatedPresenterRoleMode = $Settings.DesignatedPresenterRoleMode.value ?? $Settings.DesignatedPresenterRoleMode + $StateIsCorrect = ($CurrentState.AllowAnonymousUsersToJoinMeeting -eq $Settings.AllowAnonymousUsersToJoinMeeting) -and ($CurrentState.AllowAnonymousUsersToStartMeeting -eq $false) -and ($CurrentState.AutoAdmittedUsers -eq 'EveryoneInCompanyExcludingGuests') -and ($CurrentState.AllowPSTNUsersToBypassLobby -eq $false) -and - ($CurrentState.MeetingChatEnabledType -eq $Settings.MeetingChatEnabledType.value) -and - ($CurrentState.DesignatedPresenterRoleMode -eq $Settings.DesignatedPresenterRoleMode.value) -and + ($CurrentState.MeetingChatEnabledType -eq $MeetingChatEnabledType) -and + ($CurrentState.DesignatedPresenterRoleMode -eq $DesignatedPresenterRoleMode) -and ($CurrentState.AllowExternalParticipantGiveRequestControl -eq $false) if ($Settings.remediate -eq $true) { if ($StateIsCorrect -eq $true) { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams Global Policy already set.' -sev Info } else { - $cmdparams = @{ + $cmdParams = @{ Identity = 'Global' AllowAnonymousUsersToJoinMeeting = $Settings.AllowAnonymousUsersToJoinMeeting AllowAnonymousUsersToStartMeeting = $false AutoAdmittedUsers = 'EveryoneInCompanyExcludingGuests' AllowPSTNUsersToBypassLobby = $false - MeetingChatEnabledType = $Settings.MeetingChatEnabledType.value - DesignatedPresenterRoleMode = $Settings.DesignatedPresenterRoleMode.value + MeetingChatEnabledType = $MeetingChatEnabledType + DesignatedPresenterRoleMode = $DesignatedPresenterRoleMode AllowExternalParticipantGiveRequestControl = $false } try { - New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTeamsMeetingPolicy' -CmdParams $cmdparams + New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTeamsMeetingPolicy' -CmdParams $cmdParams Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated Teams Global Policy' -sev Info } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Teams Global Policy. Error: $ErrorMessage" -sev Error + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Teams Global Policy. Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage } } } @@ -76,7 +79,7 @@ Function Invoke-CIPPStandardTeamsGlobalMeetingPolicy { } } - if ($Setings.report -eq $true) { + if ($Settings.report -eq $true) { Add-CIPPBPAField -FieldName 'TeamsGlobalMeetingPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 index 6c14e3df7ebf..e2adde819c8a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 @@ -15,7 +15,7 @@ function Invoke-CIPPStandardTeamsMeetingsByDefault { TAG "lowimpact" ADDEDCOMPONENT - {"type":"select","multiple":false,"label":"Select value","name":"standards.TeamsMeetingsByDefault.state","options":[{"label":"Enabled","value":"true"},{"label":"Disabled","value":"false"}]} + {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.TeamsMeetingsByDefault.state","options":[{"label":"Enabled","value":"true"},{"label":"Disabled","value":"false"}]} IMPACT Low Impact POWERSHELLEQUIVALENT @@ -30,19 +30,22 @@ function Invoke-CIPPStandardTeamsMeetingsByDefault { param($Tenant, $Settings) ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsMeetingsByDefault' + # Get state value using null-coalescing operator + $state = $Settings.state.value ?? $Settings.state + $CurrentState = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig').OnlineMeetingsByDefaultEnabled - $WantedState = if ($Settings.state -eq 'true') { $true } else { $false } + $WantedState = if ($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 + 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 + if (([string]::IsNullOrWhiteSpace($state) -or $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 } @@ -50,23 +53,23 @@ function Invoke-CIPPStandardTeamsMeetingsByDefault { Write-Host 'Time to remediate' if ($StateIsCorrect -eq $false) { try { - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdParams @{ OnlineMeetingsByDefaultEnabled = $WantedState } -useSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully set the tenant TeamsMeetingsByDefault state to $($Settings.state)" -sev Info + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdParams @{ OnlineMeetingsByDefaultEnabled = $WantedState } -useSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Successfully set the tenant TeamsMeetingsByDefault state to $state" -sev Info } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set the tenant TeamsMeetingsByDefault state to $($Settings.state). Error: $ErrorMessage" -sev Error + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set the tenant TeamsMeetingsByDefault state to $state. Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage } } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant TeamsMeetingsByDefault state is already set correctly to $($Settings.state)" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "The tenant TeamsMeetingsByDefault state is already set correctly to $state" -sev Info } } if ($Settings.alert -eq $true) { if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant TeamsMeetingsByDefault is set correctly to $($Settings.state)" -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message "The tenant TeamsMeetingsByDefault is set correctly to $state" -sev Info } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant TeamsMeetingsByDefault is not set correctly to $($Settings.state)" -sev Alert + Write-LogMessage -API 'Standards' -tenant $Tenant -message "The tenant TeamsMeetingsByDefault is not set correctly to $state" -sev Alert } } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 index 14f3c3660d12..afda1581bf25 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 @@ -19,7 +19,7 @@ Function Invoke-CIPPStandardTeamsMessagingPolicy { {"type":"switch","name":"standards.TeamsMessagingPolicy.AllowUserDeleteMessage","label":"Allow User to Delete Messages","default":true} {"type":"switch","name":"standards.TeamsMessagingPolicy.AllowUserEditMessage","label":"Allow User to Edit Messages","default":true} {"type":"switch","name":"standards.TeamsMessagingPolicy.AllowUserDeleteChat","label":"Allow User to Delete Chats","default":true} - {"type":"autoComplete","multiple":false,"name":"standards.TeamsMessagingPolicy.ReadReceiptsEnabledType","label":"Read Receipts Enabled Type","options":[{"label":"User controlled","value":"UserPreference"},{"label":"Turned on for everyone","value":"Everyone"},{"label":"Turned off for everyone","value":"None"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.TeamsMessagingPolicy.ReadReceiptsEnabledType","label":"Read Receipts Enabled Type","options":[{"label":"User controlled","value":"UserPreference"},{"label":"Turned on for everyone","value":"Everyone"},{"label":"Turned off for everyone","value":"None"}]} {"type":"switch","name":"standards.TeamsMessagingPolicy.CreateCustomEmojis","label":"Allow Creating Custom Emojis","default":true} {"type":"switch","name":"standards.TeamsMessagingPolicy.DeleteCustomEmojis","label":"Allow Deleting Custom Emojis","default":false} {"type":"switch","name":"standards.TeamsMessagingPolicy.AllowSecurityEndUserReporting","label":"Allow reporting message as security concern","default":true} @@ -48,11 +48,13 @@ Function Invoke-CIPPStandardTeamsMessagingPolicy { if ($null -eq $Settings.AllowSecurityEndUserReporting) { $Settings.AllowSecurityEndUserReporting = $CurrentState.AllowSecurityEndUserReporting } if ($null -eq $Settings.AllowCommunicationComplianceEndUserReporting) { $Settings.AllowCommunicationComplianceEndUserReporting = $CurrentState.AllowCommunicationComplianceEndUserReporting } - $StateIsCorrect = ($CurrentState.AllowOwnerDeleteMessage -eq $Settings.AllowOwnerDeleteMessage) -and + $ReadReceiptsEnabledType = $Settings.ReadReceiptsEnabledType.value ?? $Settings.ReadReceiptsEnabledType + + $StateIsCorrect = ($CurrentState.AllowOwnerDeleteMessage -eq $Settings.AllowOwnerDeleteMessage) -and ($CurrentState.AllowUserDeleteMessage -eq $Settings.AllowUserDeleteMessage) -and ($CurrentState.AllowUserEditMessage -eq $Settings.AllowUserEditMessage) -and ($CurrentState.AllowUserDeleteChat -eq $Settings.AllowUserDeleteChat) -and - ($CurrentState.ReadReceiptsEnabledType -eq $Settings.ReadReceiptsEnabledType.value) -and + ($CurrentState.ReadReceiptsEnabledType -eq $ReadReceiptsEnabledType) -and ($CurrentState.CreateCustomEmojis -eq $Settings.CreateCustomEmojis) -and ($CurrentState.DeleteCustomEmojis -eq $Settings.DeleteCustomEmojis) -and ($CurrentState.AllowSecurityEndUserReporting -eq $Settings.AllowSecurityEndUserReporting) -and @@ -63,15 +65,15 @@ Function Invoke-CIPPStandardTeamsMessagingPolicy { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Global Teams Messaging policy already configured.' -sev Info } else { $cmdparams = @{ - Identity = 'Global' - AllowOwnerDeleteMessage = $Settings.AllowOwnerDeleteMessage - AllowUserDeleteMessage = $Settings.AllowUserDeleteMessage - AllowUserEditMessage = $Settings.AllowUserEditMessage - AllowUserDeleteChat = $Settings.AllowUserDeleteChat - ReadReceiptsEnabledType = $Settings.ReadReceiptsEnabledType.value - CreateCustomEmojis = $Settings.CreateCustomEmojis - DeleteCustomEmojis = $Settings.DeleteCustomEmojis - AllowSecurityEndUserReporting = $Settings.AllowSecurityEndUserReporting + Identity = 'Global' + AllowOwnerDeleteMessage = $Settings.AllowOwnerDeleteMessage + AllowUserDeleteMessage = $Settings.AllowUserDeleteMessage + AllowUserEditMessage = $Settings.AllowUserEditMessage + AllowUserDeleteChat = $Settings.AllowUserDeleteChat + ReadReceiptsEnabledType = $ReadReceiptsEnabledType + CreateCustomEmojis = $Settings.CreateCustomEmojis + DeleteCustomEmojis = $Settings.DeleteCustomEmojis + AllowSecurityEndUserReporting = $Settings.AllowSecurityEndUserReporting AllowCommunicationComplianceEndUserReporting = $Settings.AllowCommunicationComplianceEndUserReporting } @@ -80,7 +82,7 @@ Function Invoke-CIPPStandardTeamsMessagingPolicy { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated global Teams messaging policy' -sev Info } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to configure global Teams messaging policy." -sev Error -LogData $ErrorMessage + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Failed to configure global Teams messaging policy.' -sev Error -LogData $ErrorMessage } } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 index 73b7d7e97614..9cd86647571e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 @@ -19,7 +19,7 @@ function Invoke-CIPPStandardTenantDefaultTimezone { IMPACT Low Impact POWERSHELLEQUIVALENT - Update-MgBetaAdminSharepointSetting + Update-MgBetaAdminSharePointSetting RECOMMENDEDBY UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 index ad965f1d28d5..d5d3bb1e22f9 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 @@ -13,7 +13,7 @@ function Invoke-CIPPStandardTransportRuleTemplate { CAT Templates DISABLEDFEATURES - + IMPACT Medium ADDEDCOMPONENT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 index 265d37507f8b..6f2ab4f113d0 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 @@ -15,7 +15,7 @@ function Invoke-CIPPStandardUserSubmissions { TAG "mediumimpact" ADDEDCOMPONENT - {"type":"select","multiple":false,"label":"Select value","name":"standards.UserSubmissions.state","options":[{"label":"Enabled","value":"enable"},{"label":"Disabled","value":"disable"}]} + {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.UserSubmissions.state","options":[{"label":"Enabled","value":"enable"},{"label":"Disabled","value":"disable"}]} {"type":"textField","name":"standards.UserSubmissions.email","required":false,"label":"Destination email address"} IMPACT Medium Impact @@ -31,16 +31,19 @@ function Invoke-CIPPStandardUserSubmissions { param($Tenant, $Settings) ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'UserSubmissions' + # Get state value using null-coalescing operator + $state = $Settings.state.value ?? $Settings.state + # Input validation if ($Settings.remediate -eq $true -or $Settings.alert -eq $true) { - if (!($Settings.state -eq 'enable' -or $Settings.state -eq 'disable')) { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'UserSubmissions: Invalid state parameter set' -sev Error + if (!($state -eq 'enable' -or $state -eq 'disable')) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'UserSubmissions: Invalid state parameter set' -sev Error Return } if (!([string]::IsNullOrWhiteSpace($Settings.email))) { if ($Settings.email -notmatch '@') { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'UserSubmissions: Invalid Email parameter set' -sev Error + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'UserSubmissions: Invalid Email parameter set' -sev Error Return } } @@ -65,7 +68,7 @@ function Invoke-CIPPStandardUserSubmissions { ($PolicyState.ReportPhishToCustomizedAddress -eq $true) -and ($PolicyState.ReportPhishAddresses -eq $Settings.email) $RuleIsCorrect = ($RuleState.State -eq 'Enabled') -and - ($RuleSteate.SentTo -eq $Settings.email) + ($RuleState.SentTo -eq $Settings.email) } } else { if ($PolicyState.length -eq 0) { @@ -85,9 +88,9 @@ function Invoke-CIPPStandardUserSubmissions { if ($Settings.report -eq $true) { if ($PolicyState.length -eq 0) { - Add-CIPPBPAField -FieldName 'UserSubmissionPolicy' -FieldValue $false -StoreAs bool -Tenant $tenant + Add-CIPPBPAField -FieldName 'UserSubmissionPolicy' -FieldValue $false -StoreAs bool -Tenant $Tenant } else { - Add-CIPPBPAField -FieldName 'UserSubmissionPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant + Add-CIPPBPAField -FieldName 'UserSubmissionPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant } } @@ -97,7 +100,7 @@ function Invoke-CIPPStandardUserSubmissions { if ($StateIsCorrect -eq $true) { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'User Submission policy is already configured' -sev Info } else { - if ($Settings.state -eq 'enable') { + if ($state -eq 'enable') { if (([string]::IsNullOrWhiteSpace($Settings.email))) { $PolicyParams = @{ EnableReportToMicrosoft = $true @@ -130,20 +133,20 @@ function Invoke-CIPPStandardUserSubmissions { if ($PolicyState.length -eq 0) { try { - New-ExoRequest -tenantid $Tenant -cmdlet 'New-ReportSubmissionPolicy' -cmdparams $PolicyParams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $tenant -message 'User Submission policy created.' -sev Info + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'New-ReportSubmissionPolicy' -cmdParams $PolicyParams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'User Submission policy created.' -sev Info } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create User Submission policy. Error: $ErrorMessage" -sev Error + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create User Submission policy. Error: $($ErrorMessage.NormalizedError)" -sev Error } } else { try { $PolicyParams.Add('Identity', 'DefaultReportSubmissionPolicy') - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-ReportSubmissionPolicy' -cmdParams $PolicyParams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $tenant -message "User Submission policy state set to $($Settings.state)." -sev Info + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-ReportSubmissionPolicy' -cmdParams $PolicyParams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "User Submission policy state set to $state." -sev Info } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set User Submission policy state to $($Settings.state). Error: $ErrorMessage" -sev Error + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set User Submission policy state to $state. Error: $($ErrorMessage.NormalizedError)" -sev Error } } @@ -152,20 +155,20 @@ function Invoke-CIPPStandardUserSubmissions { try { $RuleParams.Add('Name', 'DefaultReportSubmissionRule') $RuleParams.Add('ReportSubmissionPolicy', 'DefaultReportSubmissionPolicy') - New-ExoRequest -tenantid $Tenant -cmdlet 'New-ReportSubmissionRule' -cmdparams $RuleParams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $tenant -message 'User Submission rule created.' -sev Info + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'New-ReportSubmissionRule' -cmdParams $RuleParams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'User Submission rule created.' -sev Info } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create User Submission rule. Error: $ErrorMessage" -sev Error + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create User Submission rule. Error: $($ErrorMessage.NormalizedError)" -sev Error } } else { try { $RuleParams.Add('Identity', 'DefaultReportSubmissionRule') - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-ReportSubmissionRule' -cmdParams $RuleParams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $tenant -message 'User Submission rule set to enabled.' -sev Info + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-ReportSubmissionRule' -cmdParams $RuleParams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'User Submission rule set to enabled.' -sev Info } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to enable User Submission rule. Error: $ErrorMessage" -sev Error + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to enable User Submission rule. Error: $($ErrorMessage.NormalizedError)" -sev Error } } } @@ -175,12 +178,12 @@ function Invoke-CIPPStandardUserSubmissions { if ($Settings.alert -eq $true) { if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'User Submission policy is properly configured.' -sev Info + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'User Submission policy is properly configured.' -sev Info } else { if ($Policy.EnableReportToMicrosoft -eq $true) { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'User Submission policy is enabled but incorrectly configured' -sev Alert + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'User Submission policy is enabled but incorrectly configured' -sev Alert } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'User Submission policy is disabled.' -sev Alert + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'User Submission policy is disabled.' -sev Alert } } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 index cbb3e14e1329..fe46ed9e9d44 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 @@ -17,7 +17,7 @@ function Invoke-CIPPStandardcalDefault { DISABLEDFEATURES ADDEDCOMPONENT - {"type":"select","multiple":false,"label":"Select Sharing Level","name":"standards.calDefault.permissionlevel","options":[{"label":"Owner - The user can create, read, edit, and delete all items in the folder, and create subfolders. The user is both folder owner and folder contact.","value":"Owner"},{"label":"Publishing Editor - The user can create, read, edit, and delete all items in the folder, and create subfolders.","value":"PublishingEditor"},{"label":"Editor - The user can create items in the folder. The contents of the folder do not appear.","value":"Editor"},{"label":"Publishing Author. The user can read, create all items/subfolders. Can modify and delete only items they create.","value":"PublishingAuthor"},{"label":"Author - The user can create and read items, and modify and delete items that they create.","value":"Author"},{"label":"Non Editing Author - The user has full read access and create items. Can can delete only own items.","value":"NonEditingAuthor"},{"label":"Reviewer - The user can read all items in the folder.","value":"Reviewer"},{"label":"Contributor - The user can create items and folders.","value":"Contributor"},{"label":"Availability Only - Indicates that the user can view only free/busy time within the calendar.","value":"AvailabilityOnly"},{"label":"Limited Details - The user can view free/busy time within the calendar and the subject and location of appointments.","value":"LimitedDetails"},{"label":"None - The user has no permissions on the folder.","value":"none"}]} + {"type":"autoComplete","multiple":false,"label":"Select Sharing Level","name":"standards.calDefault.permissionLevel","options":[{"label":"Owner - The user can create, read, edit, and delete all items in the folder, and create subfolders. The user is both folder owner and folder contact.","value":"Owner"},{"label":"Publishing Editor - The user can create, read, edit, and delete all items in the folder, and create subfolders.","value":"PublishingEditor"},{"label":"Editor - The user can create items in the folder. The contents of the folder do not appear.","value":"Editor"},{"label":"Publishing Author. The user can read, create all items/subfolders. Can modify and delete only items they create.","value":"PublishingAuthor"},{"label":"Author - The user can create and read items, and modify and delete items that they create.","value":"Author"},{"label":"Non Editing Author - The user has full read access and create items. Can can delete only own items.","value":"NonEditingAuthor"},{"label":"Reviewer - The user can read all items in the folder.","value":"Reviewer"},{"label":"Contributor - The user can create items and folders.","value":"Contributor"},{"label":"Availability Only - Indicates that the user can view only free/busy time within the calendar.","value":"AvailabilityOnly"},{"label":"Limited Details - The user can view free/busy time within the calendar and the subject and location of appointments.","value":"LimitedDetails"},{"label":"None - The user has no permissions on the folder.","value":"none"}]} IMPACT Low Impact POWERSHELLEQUIVALENT @@ -32,9 +32,11 @@ function Invoke-CIPPStandardcalDefault { param($Tenant, $Settings, $QueueItem) ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'calDefault' + # Get permissionlevel value using null-coalescing operator + $permissionLevel = $Settings.permissionlevel.value ?? $Settings.permissionlevel + # Input validation - $Settings.permissionlevel = $Settings.permissionlevel.value ? $Settings.permissionlevel.value : $Settings.permissionlevel - if ([string]::IsNullOrWhiteSpace($Settings.permissionlevel) -or $Settings.permissionlevel -eq 'Select a value') { + if ([string]::IsNullOrWhiteSpace($permissionLevel) -or $permissionLevel -eq 'Select a value') { Write-LogMessage -API 'Standards' -tenant $tenant -message 'calDefault: Invalid permissionlevel parameter set' -sev Error Return } @@ -66,18 +68,18 @@ function Invoke-CIPPStandardcalDefault { New-ExoRequest -tenantid $Tenant -cmdlet 'Get-MailboxFolderStatistics' -cmdParams @{identity = $Mailbox.UserPrincipalName; FolderScope = 'Calendar' } -Anchor $Mailbox.UserPrincipalName | Where-Object { $_.FolderType -eq 'Calendar' } | ForEach-Object { try { - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-MailboxFolderPermission' -cmdparams @{Identity = "$($Mailbox.UserPrincipalName):$($_.FolderId)"; User = 'Default'; AccessRights = $Settings.permissionlevel } -Anchor $Mailbox.UserPrincipalName - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Set default folder permission for $($Mailbox.UserPrincipalName):\$($_.Name) to $($Settings.permissionlevel)" -sev Debug + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-MailboxFolderPermission' -cmdParams @{Identity = "$($Mailbox.UserPrincipalName):$($_.FolderId)"; User = 'Default'; AccessRights = $permissionLevel } -Anchor $Mailbox.UserPrincipalName + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Set default folder permission for $($Mailbox.UserPrincipalName):\$($_.Name) to $permissionLevel" -sev Debug $SuccessCounter++ } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + $ErrorMessage = Get-CippException -Exception $_ Write-Host "Setting cal failed: $ErrorMessage" - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Could not set default calendar permissions for $($Mailbox.UserPrincipalName). Error: $ErrorMessage" -sev Error + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Could not set default calendar permissions for $($Mailbox.UserPrincipalName). Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage } } } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Could not set default calendar permissions for $($Mailbox.UserPrincipalName). Error: $ErrorMessage" -sev Error + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Could not set default calendar permissions for $($Mailbox.UserPrincipalName). Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage } $processedMailboxes++ if ($processedMailboxes % 25 -eq 0) { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 index dc6b2184a4d5..1f1f03b645d5 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 @@ -18,7 +18,7 @@ function Invoke-CIPPStandarddisableMacSync { IMPACT High Impact POWERSHELLEQUIVALENT - Update-MgAdminSharepointSetting + Update-MgAdminSharePointSetting RECOMMENDEDBY UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 index f6840bafc092..aec44ee5a39c 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 @@ -7,15 +7,15 @@ function Invoke-CIPPStandardintuneDeviceReg { .SYNOPSIS (Label) Set Maximum Number of Devices per user .DESCRIPTION - (Helptext) sets the maximum number of devices that can be registered by a user. A value of 0 disables device registration by users - (DocsDescription) sets the maximum number of devices that can be registered by a user. A value of 0 disables device registration by users + (Helptext) Sets the maximum number of devices that can be registered by a user. A value of 0 disables device registration by users + (DocsDescription) Sets the maximum number of devices that can be registered by a user. A value of 0 disables device registration by users .NOTES CAT Intune Standards TAG "mediumimpact" ADDEDCOMPONENT - {"type":"number","name":"standards.intuneDeviceReg.max","label":"Maximum devices (Enter 2147483647 for unlimited.)"} + {"type":"number","name":"standards.intuneDeviceReg.max","label":"Maximum devices (Enter 2147483647 for unlimited.)","required":true} IMPACT Medium Impact POWERSHELLEQUIVALENT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 index 3cab0708f09d..cc955e92a9a5 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 @@ -21,6 +21,7 @@ function Invoke-CIPPStandardintuneDeviceRetirementDays { POWERSHELLEQUIVALENT Graph API RECOMMENDEDBY + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardlaps.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardlaps.ps1 index da89f92a6795..4229ea55dd68 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardlaps.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardlaps.ps1 @@ -20,6 +20,7 @@ function Invoke-CIPPStandardlaps { POWERSHELLEQUIVALENT Portal or Graph API RECOMMENDEDBY + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 index 277263b94e61..4faae11a6f95 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 @@ -16,13 +16,14 @@ function Invoke-CIPPStandardsharingCapability { "highimpact" "CIS" ADDEDCOMPONENT - {"type":"select","multiple":false,"label":"Select Sharing Level","name":"standards.sharingCapability.Level","options":[{"label":"Users can share only with people in the organization. No external sharing is allowed.","value":"disabled"},{"label":"Users can share with new and existing guests. Guests must sign in or provide a verification code.","value":"externalUserSharingOnly"},{"label":"Users can share with anyone by using links that do not require sign-in.","value":"externalUserAndGuestSharing"},{"label":"Users can share with existing guests (those already in the directory of the organization).","value":"existingExternalUserSharingOnly"}]} + {"type":"autoComplete","multiple":false,"label":"Select Sharing Level","name":"standards.sharingCapability.Level","options":[{"label":"Users can share only with people in the organization. No external sharing is allowed.","value":"disabled"},{"label":"Users can share with new and existing guests. Guests must sign in or provide a verification code.","value":"externalUserSharingOnly"},{"label":"Users can share with anyone by using links that do not require sign-in.","value":"externalUserAndGuestSharing"},{"label":"Users can share with existing guests (those already in the directory of the organization).","value":"existingExternalUserSharingOnly"}]} IMPACT High Impact POWERSHELLEQUIVALENT - Update-MgBetaAdminSharepointSetting + Update-MgBetaAdminSharePointSetting RECOMMENDEDBY "CIS" + "CIPP" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK @@ -35,38 +36,45 @@ function Invoke-CIPPStandardsharingCapability { $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'sharingCapability' -FieldValue $CurrentInfo.sharingCapability -StoreAs string -Tenant $tenant + Add-CIPPBPAField -FieldName 'sharingCapability' -FieldValue $CurrentInfo.sharingCapability -StoreAs string -Tenant $Tenant } + # Get level value using null-coalescing operator + $level = $Settings.Level.value ?? $Settings.Level + # Input validation - if (([string]::IsNullOrWhiteSpace($Settings.Level -or $Settings.Level -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 + if (([string]::IsNullOrWhiteSpace($level) -or $level -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) { - if ($CurrentInfo.sharingCapability -eq $Settings.Level) { - Write-Host "Sharing level is already set to $($Settings.Level)" - Write-LogMessage -API 'Standards' -tenant $tenant -message "Sharing level is already set to $($Settings.Level)" -sev Info + if ($CurrentInfo.sharingCapability -eq $level) { + Write-Host "Sharing level is already set to $level" + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Sharing level is already set to $level" -sev Info } else { - Write-Host "Setting sharing level to $($Settings.Level) from $($CurrentInfo.sharingCapability)" + Write-Host "Setting sharing level to $level from $($CurrentInfo.sharingCapability)" try { - $null = New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -AsApp $true -Type patch -Body "{`"sharingCapability`":`"$($Settings.Level)`"}" -ContentType 'application/json' - Write-LogMessage -API 'Standards' -tenant $tenant -message "Set sharing level to $($Settings.Level) from $($CurrentInfo.sharingCapability)" -sev Info + $body = @{ + sharingCapability = $level + } + $bodyJson = ConvertTo-Json -InputObject $body -Compress + $null = New-GraphPostRequest -tenantid $Tenant -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -AsApp $true -Type patch -Body $bodyJson -ContentType 'application/json' + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Set sharing level to $level from $($CurrentInfo.sharingCapability)" -sev Info } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set sharing level to $($Settings.Level): $ErrorMessage" -sev Error + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set sharing level to $level : $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage } } } if ($Settings.alert -eq $true) { - if ($CurrentInfo.sharingCapability -eq $Settings.Level) { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Sharing level is set to $($Settings.Level)" -sev Info + if ($CurrentInfo.sharingCapability -eq $level) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Sharing level is set to $level" -sev Info } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message "Sharing level is not set to $($Settings.Level)" -sev Alert + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Sharing level is not set to $level" -sev Alert } } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingDomainRestriction.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingDomainRestriction.ps1 index 098b0ef3e17e..0b736f730720 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingDomainRestriction.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingDomainRestriction.ps1 @@ -16,12 +16,12 @@ function Invoke-CIPPStandardsharingDomainRestriction { "highimpact" "CIS" ADDEDCOMPONENT - {"type":"select","multiple":false,"name":"standards.sharingDomainRestriction.Mode","label":"Limit external sharing by domains","options":[{"label":"Off","value":"none"},{"label":"Restrict sharing to specific domains","value":"allowList"},{"label":"Block sharing to specific domains","value":"blockList"}]} + {"type":"autoComplete","multiple":false,"name":"standards.sharingDomainRestriction.Mode","label":"Limit external sharing by domains","options":[{"label":"Off","value":"none"},{"label":"Restrict sharing to specific domains","value":"allowList"},{"label":"Block sharing to specific domains","value":"blockList"}]} {"type":"textField","name":"standards.sharingDomainRestriction.Domains","label":"Domains to allow/block, comma separated","required":false} IMPACT High Impact POWERSHELLEQUIVALENT - Update-MgAdminSharepointSetting + Update-MgAdminSharePointSetting RECOMMENDEDBY UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block @@ -34,13 +34,16 @@ function Invoke-CIPPStandardsharingDomainRestriction { $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) { + # Get mode value using null-coalescing operator + $mode = $Settings.Mode.value ?? $Settings.Mode + + if ($mode -eq 'none' -or $null -eq $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))) + $StateIsCorrect = ($CurrentState.sharingDomainRestrictionMode -eq $mode) -and + ($mode -eq 'allowList' -and (!(Compare-Object -ReferenceObject $CurrentState.sharingAllowedDomainList -DifferenceObject $SelectedDomains))) -or + ($mode -eq 'blockList' -and (!(Compare-Object -ReferenceObject $CurrentState.sharingBlockedDomainList -DifferenceObject $SelectedDomains))) } if ($Settings.remediate -eq $true) { @@ -48,16 +51,16 @@ function Invoke-CIPPStandardsharingDomainRestriction { Write-LogMessage -API 'Standards' -tenant $tenant -message 'Sharing Domain Restriction is already correctly configured' -sev Info } else { $Body = @{ - sharingDomainRestrictionMode = $Settings.Mode + sharingDomainRestrictionMode = $mode } - if ($Settings.Mode -eq 'AllowList') { + if ($mode -eq 'AllowList') { $Body.Add('sharingAllowedDomainList', $SelectedDomains) - } elseif ($Settings.Mode -eq 'BlockList') { + } elseif ($mode -eq 'BlockList') { $Body.Add('sharingBlockedDomainList', $SelectedDomains) } - $cmdparams = @{ + $cmdParams = @{ tenantid = $tenant uri = 'https://graph.microsoft.com/beta/admin/sharepoint/settings' AsApp = $true @@ -67,11 +70,11 @@ function Invoke-CIPPStandardsharingDomainRestriction { } try { - New-GraphPostRequest @cmdparams + $null = 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 + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to update Sharing Domain Restriction settings. Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage } } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardunmanagedSync.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardunmanagedSync.ps1 index 416af1a6ded7..c659ba14750b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardunmanagedSync.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardunmanagedSync.ps1 @@ -18,7 +18,7 @@ function Invoke-CIPPStandardunmanagedSync { IMPACT High Impact POWERSHELLEQUIVALENT - Update-MgAdminSharepointSetting + Update-MgAdminSharePointSetting RECOMMENDEDBY UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block diff --git a/Tools/Update-StandardsComments.ps1 b/Tools/Update-StandardsComments.ps1 index c3d7c9cc30f1..6f5cc8397db9 100644 --- a/Tools/Update-StandardsComments.ps1 +++ b/Tools/Update-StandardsComments.ps1 @@ -73,7 +73,7 @@ foreach ($Standard in $StandardsInfo) { if ($Content -match $Regex) { $NewComment = [System.Collections.Generic.List[string]]::new() - # Add the initial scatic comments + # Add the initial static comments $NewComment.Add("<#`r`n") $NewComment.Add(" .FUNCTIONALITY`r`n") $NewComment.Add(" Internal`r`n") From eeb6a6949b16b8e023df394ba1cd0e4399682e62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sat, 15 Feb 2025 13:08:58 +0100 Subject: [PATCH 003/167] update comments and fix RetentionPolicyTag standard --- ...nvoke-CIPPStandardActivityBasedTimeout.ps1 | 1 - .../Standards/Invoke-CIPPStandardAddDKIM.ps1 | 1 - .../Invoke-CIPPStandardAnonReportDisable.ps1 | 1 - .../Invoke-CIPPStandardAntiPhishPolicy.ps1 | 1 - .../Invoke-CIPPStandardAppDeploy.ps1 | 1 - .../Invoke-CIPPStandardAtpPolicyForO365.ps1 | 1 - .../Standards/Invoke-CIPPStandardAuditLog.ps1 | 1 - ...Invoke-CIPPStandardAuthMethodsSettings.ps1 | 1 - .../Invoke-CIPPStandardAutoAddProxy.ps1 | 28 +++ .../Invoke-CIPPStandardAutoExpandArchive.ps1 | 1 - .../Standards/Invoke-CIPPStandardBranding.ps1 | 1 - .../Invoke-CIPPStandardCloudMessageRecall.ps1 | 1 - ...-CIPPStandardConditionalAccessTemplate.ps1 | 2 +- ...voke-CIPPStandardDeletedUserRentention.ps1 | 1 - ...ndardDisableAdditionalStorageProviders.ps1 | 1 - .../Invoke-CIPPStandardDisableAppCreation.ps1 | 1 - ...StandardDisableExternalCalendarSharing.ps1 | 1 - ...voke-CIPPStandardDisableGuestDirectory.ps1 | 1 - ...voke-CIPPStandardDisableM365GroupUsers.ps1 | 1 - ...nvoke-CIPPStandardDisableOutlookAddins.ps1 | 1 - .../Invoke-CIPPStandardDisableReshare.ps1 | 1 - ...IPPStandardDisableSharePointLegacyAuth.ps1 | 1 - ...nvoke-CIPPStandardDisableSharedMailbox.ps1 | 1 - .../Invoke-CIPPStandardDisableTNEF.ps1 | 1 - ...voke-CIPPStandardDisableTenantCreation.ps1 | 1 - .../Invoke-CIPPStandardDisableViva.ps1 | 1 - ...e-CIPPStandardEXODisableAutoForwarding.ps1 | 1 - ...e-CIPPStandardEnableAppConsentRequests.ps1 | 1 - ...voke-CIPPStandardEnableCustomerLockbox.ps1 | 1 - .../Invoke-CIPPStandardEnableFIDO2.ps1 | 1 - ...Invoke-CIPPStandardEnableHardwareOAuth.ps1 | 1 - ...nvoke-CIPPStandardEnableLitigationHold.ps1 | 1 - .../Invoke-CIPPStandardEnableMailTips.ps1 | 1 - ...voke-CIPPStandardEnableMailboxAuditing.ps1 | 1 - ...voke-CIPPStandardEnableOnlineArchiving.ps1 | 1 - .../Invoke-CIPPStandardEnablePronouns.ps1 | 1 - .../Invoke-CIPPStandardExternalMFATrusted.ps1 | 1 - .../Invoke-CIPPStandardFocusedInbox.ps1 | 1 - ...PStandardGlobalQuarantineNotifications.ps1 | 1 - .../Invoke-CIPPStandardGroupTemplate.ps1 | 2 +- ...e-CIPPStandardIntuneComplianceSettings.ps1 | 1 - .../Invoke-CIPPStandardIntuneTemplate.ps1 | 2 +- .../Invoke-CIPPStandardMailContacts.ps1 | 1 - ...Invoke-CIPPStandardMalwareFilterPolicy.ps1 | 1 - .../Invoke-CIPPStandardMessageExpiration.ps1 | 1 - .../Standards/Invoke-CIPPStandardNudgeMFA.ps1 | 1 - .../Invoke-CIPPStandardOauthConsent.ps1 | 1 - .../Invoke-CIPPStandardOauthConsentLowSec.ps1 | 1 - .../Invoke-CIPPStandardOutBoundSpamAlert.ps1 | 1 - ...CIPPStandardPWcompanionAppAllowedState.ps1 | 1 - ...rdPWdisplayAppInformationRequiredState.ps1 | 1 - ...oke-CIPPStandardPasswordExpireDisabled.ps1 | 1 - .../Invoke-CIPPStandardPhishProtection.ps1 | 1 - .../Invoke-CIPPStandardProfilePhotos.ps1 | 1 - ...oke-CIPPStandardQuarantineRequestAlert.ps1 | 1 - ...Invoke-CIPPStandardRetentionPolicyTag.ps1} | 193 ++++++++++-------- .../Invoke-CIPPStandardRotateDKIM.ps1 | 1 - .../Invoke-CIPPStandardSPAzureB2B.ps1 | 1 - .../Invoke-CIPPStandardSPDirectSharing.ps1 | 1 - ...e-CIPPStandardSPDisableLegacyWorkflows.ps1 | 1 - ...ke-CIPPStandardSPDisallowInfectedFiles.ps1 | 1 - ...e-CIPPStandardSPExternalUserExpiration.ps1 | 1 - ...nvoke-CIPPStandardSafeAttachmentPolicy.ps1 | 1 - .../Invoke-CIPPStandardSafeLinksPolicy.ps1 | 1 - ...oke-CIPPStandardSendReceiveLimitTenant.ps1 | 1 - .../Invoke-CIPPStandardSpoofWarn.ps1 | 1 - .../Invoke-CIPPStandardStaleEntraDevices.ps1 | 1 - .../Standards/Invoke-CIPPStandardTAP.ps1 | 1 - ...voke-CIPPStandardTeamsEmailIntegration.ps1 | 1 - .../Invoke-CIPPStandardTeamsEnrollUser.ps1 | 1 - ...e-CIPPStandardTeamsExternalFileSharing.ps1 | 1 - ...e-CIPPStandardTeamsGlobalMeetingPolicy.ps1 | 1 - ...oke-CIPPStandardTeamsMeetingsByDefault.ps1 | 1 - ...voke-CIPPStandardTenantDefaultTimezone.ps1 | 1 - ...voke-CIPPStandardTransportRuleTemplate.ps1 | 2 +- .../Invoke-CIPPStandardallowOAuthTokens.ps1 | 1 - .../Invoke-CIPPStandardallowOTPTokens.ps1 | 1 - .../Invoke-CIPPStandardcalDefault.ps1 | 1 - ...voke-CIPPStandardintuneBrandingProfile.ps1 | 1 - ...CIPPStandardintuneDeviceRetirementDays.ps1 | 1 - .../Standards/Invoke-CIPPStandardlaps.ps1 | 1 - .../Invoke-CIPPStandardsharingCapability.ps1 | 1 - ...e-CIPPStandardsharingDomainRestriction.ps1 | 1 - 83 files changed, 139 insertions(+), 167 deletions(-) rename Modules/CIPPCore/Public/Standards/{Invoke-CIPPStandardRetentionPolicy.ps1 => Invoke-CIPPStandardRetentionPolicyTag.ps1} (80%) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 index 02558d5a3716..335d860c6200 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardActivityBasedTimeout { CAT Global Standards TAG - "mediumimpact" "CIS" "spo_idle_session_timeout" ADDEDCOMPONENT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 index 7d16160baeef..a57df85e9e4a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardAddDKIM { CAT Exchange Standards TAG - "lowimpact" "CIS" ADDEDCOMPONENT IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAnonReportDisable.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAnonReportDisable.ps1 index 668323a5173e..23fbae4dc8f8 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAnonReportDisable.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAnonReportDisable.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardAnonReportDisable { CAT Global Standards TAG - "lowimpact" ADDEDCOMPONENT IMPACT Low Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 index 888a7fca3608..8e3eee48d96c 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardAntiPhishPolicy { CAT Defender Standards TAG - "lowimpact" "CIS" "mdo_safeattachments" "mdo_highconfidencespamaction" diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAppDeploy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAppDeploy.ps1 index bd9b80c3c0c3..4e6802efeb33 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAppDeploy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAppDeploy.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardAppDeploy { CAT Entra (AAD) Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"textField","name":"standards.AppDeploy.appids","label":"Application IDs, comma separated"} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 index 510c9fdf9e08..f7e369859105 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardAtpPolicyForO365 { CAT Defender Standards TAG - "lowimpact" "CIS" ADDEDCOMPONENT {"type":"switch","label":"Allow people to click through Protected View even if Safe Documents identified the file as malicious","name":"standards.AtpPolicyForO365.AllowSafeDocsOpen","default":false,"required":false} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 index 079371875e27..c2ce718ae008 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardAuditLog { CAT Global Standards TAG - "lowimpact" "CIS" "mip_search_auditlog" ADDEDCOMPONENT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuthMethodsSettings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuthMethodsSettings.ps1 index 5cfd3d47d35f..18ab2554d4a5 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuthMethodsSettings.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuthMethodsSettings.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardAuthMethodsSettings { CAT Entra (AAD) Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"creatable":false,"required":false,"name":"standards.AuthMethodsSettings.ReportSuspiciousActivity","label":"Report Suspicious Activity Settings","options":[{"label":"Microsoft managed","value":"default"},{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} {"type":"autoComplete","multiple":false,"creatable":false,"required":false,"name":"standards.AuthMethodsSettings.SystemCredential","label":"System Credential Preferences","options":[{"label":"Microsoft managed","value":"default"},{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoAddProxy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoAddProxy.ps1 index e74ff3a89996..7ad0a6b2e11f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoAddProxy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoAddProxy.ps1 @@ -1,4 +1,32 @@ function Invoke-CIPPStandardAutoAddProxy { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) AutoAddProxy + .SYNOPSIS + (Label) Automatically deploy proxy addresses + .DESCRIPTION + (Helptext) Automatically adds all available domains as a proxy address. + (DocsDescription) Automatically finds all available domain names in the tenant, and tries to add proxy addresses based on the user's UPN to each of these. + .NOTES + CAT + Exchange Standards + TAG + "CIS" + ADDEDCOMPONENT + IMPACT + Medium Impact + POWERSHELLEQUIVALENT + Set-Mailbox -EmailAddresses @{add=\$EmailAddress} + RECOMMENDEDBY + DISABLEDFEATURES + + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/exchange-standards#medium-impact + #> param( $Tenant, $Settings, diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoExpandArchive.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoExpandArchive.ps1 index a7bf50586167..9945f982b524 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoExpandArchive.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoExpandArchive.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardAutoExpandArchive { CAT Exchange Standards TAG - "lowimpact" ADDEDCOMPONENT IMPACT Low Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBranding.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBranding.ps1 index 6f6529aa37bf..d4190433c941 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBranding.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBranding.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardBranding { CAT Global Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"textField","name":"standards.Branding.signInPageText","label":"Sign-in page text","required":false} {"type":"textField","name":"standards.Branding.usernameHintText","label":"Username hint Text","required":false} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 index 1c22840862c0..def36fadcb5e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardCloudMessageRecall { CAT Exchange Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.CloudMessageRecall.state","options":[{"label":"Enabled","value":"true"},{"label":"Disabled","value":"false"}]} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccessTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccessTemplate.ps1 index b4fd5026f806..4f3dcd23bad6 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccessTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccessTemplate.ps1 @@ -17,7 +17,7 @@ function Invoke-CIPPStandardConditionalAccessTemplate { DISABLEDFEATURES IMPACT - High + High Impact ADDEDCOMPONENT {"type":"autoComplete","name":"TemplateList","multiple":false,"label":"Select Conditional Access Template","api":{"url":"/api/ListCATemplates","labelField":"displayName","valueField":"GUID","queryKey":"ListCATemplates"}} {"name":"state","label":"What state should we deploy this template in?","type":"radio","options":[{"value":"donotchange","label":"Do not change state"},{"value":"Enabled","label":"Set to enabled"},{"value":"Disabled","label":"Set to disabled"},{"value":"enabledForReportingButNotEnforced","label":"Set to report only"}]} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 index 8db43324ab39..428327b1fe99 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDeletedUserRentention { CAT SharePoint Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"name":"standards.DeletedUserRentention.Days","label":"Retention time (Default 30 days)","options":[{"label":"30 days","value":"30"},{"label":"90 days","value":"90"},{"label":"1 year","value":"365"},{"label":"2 years","value":"730"},{"label":"3 years","value":"1095"},{"label":"4 years","value":"1460"},{"label":"5 years","value":"1825"},{"label":"6 years","value":"2190"},{"label":"7 years","value":"2555"},{"label":"8 years","value":"2920"},{"label":"9 years","value":"3285"},{"label":"10 years","value":"3650"}]} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAdditionalStorageProviders.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAdditionalStorageProviders.ps1 index d0061c46b32d..0335b7dcace4 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAdditionalStorageProviders.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAdditionalStorageProviders.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableAdditionalStorageProviders { CAT Exchange Standards TAG - "lowimpact" "CIS" "exo_storageproviderrestricted" ADDEDCOMPONENT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAppCreation.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAppCreation.ps1 index f96fcbb29bb4..295d5e9b87f8 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAppCreation.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAppCreation.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableAppCreation { CAT Entra (AAD) Standards TAG - "lowimpact" "CIS" ADDEDCOMPONENT IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExternalCalendarSharing.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExternalCalendarSharing.ps1 index f920de3c18d7..8270a259292b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExternalCalendarSharing.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExternalCalendarSharing.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableExternalCalendarSharing { CAT Exchange Standards TAG - "lowimpact" "CIS" "exo_individualsharing" ADDEDCOMPONENT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuestDirectory.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuestDirectory.ps1 index 1c1468dbfa6a..e0ecf6b19586 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuestDirectory.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuestDirectory.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableGuestDirectory { CAT Global Standards TAG - "lowimpact" ADDEDCOMPONENT IMPACT Low Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableM365GroupUsers.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableM365GroupUsers.ps1 index ceb53907e1e0..b241ae9e19ca 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableM365GroupUsers.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableM365GroupUsers.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableM365GroupUsers { CAT Entra (AAD) Standards TAG - "lowimpact" ADDEDCOMPONENT IMPACT Low Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 index b6507d5710e5..e011c6b46878 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableOutlookAddins { CAT Exchange Standards TAG - "mediumimpact" "CIS" "exo_outlookaddins" ADDEDCOMPONENT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 index 72eec7f32183..158c1fa7010b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableReshare { CAT SharePoint Standards TAG - "highimpact" "CIS" ADDEDCOMPONENT IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharePointLegacyAuth.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharePointLegacyAuth.ps1 index d92d900faceb..a9e5d0d8c51c 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharePointLegacyAuth.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharePointLegacyAuth.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableSharePointLegacyAuth { CAT SharePoint Standards TAG - "mediumimpact" "CIS" "spo_legacy_auth" ADDEDCOMPONENT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharedMailbox.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharedMailbox.ps1 index 767d670878d7..b3825fe36b83 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharedMailbox.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharedMailbox.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableSharedMailbox { CAT Exchange Standards TAG - "mediumimpact" "CIS" ADDEDCOMPONENT IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 index 1e0f01ee4bcc..293ce18f7762 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableTNEF { CAT Exchange Standards TAG - "lowimpact" ADDEDCOMPONENT IMPACT Low Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTenantCreation.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTenantCreation.ps1 index 3dac87cd1b13..a167603091de 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTenantCreation.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTenantCreation.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableTenantCreation { CAT Entra (AAD) Standards TAG - "lowimpact" "CIS" ADDEDCOMPONENT IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableViva.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableViva.ps1 index c44565c5b519..ac7b6b207575 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableViva.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableViva.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableViva { CAT Exchange Standards TAG - "lowimpact" ADDEDCOMPONENT IMPACT Low Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 index e3ccc3e5eb51..d2ab1cf7088d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardEXODisableAutoForwarding { CAT Exchange Standards TAG - "highimpact" "CIS" "mdo_autoforwardingmode" "mdo_blockmailforward" diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableAppConsentRequests.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableAppConsentRequests.ps1 index dd64008cff74..7db52549e3dc 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableAppConsentRequests.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableAppConsentRequests.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardEnableAppConsentRequests { CAT Entra (AAD) Standards TAG - "lowimpact" "CIS" ADDEDCOMPONENT {"type":"AdminRolesMultiSelect","label":"App Consent Reviewer Roles","name":"standards.EnableAppConsentRequests.ReviewerRoles"} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableCustomerLockbox.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableCustomerLockbox.ps1 index 7434e8035e07..ef686a9cccb1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableCustomerLockbox.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableCustomerLockbox.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardEnableCustomerLockbox { CAT Global Standards TAG - "lowimpact" "CIS" "CustomerLockBoxEnabled" ADDEDCOMPONENT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableFIDO2.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableFIDO2.ps1 index 9848446c8756..bed8799542aa 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableFIDO2.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableFIDO2.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardEnableFIDO2 { CAT Entra (AAD) Standards TAG - "lowimpact" ADDEDCOMPONENT IMPACT Low Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableHardwareOAuth.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableHardwareOAuth.ps1 index 4394cf0740cd..811d20565c9f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableHardwareOAuth.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableHardwareOAuth.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardEnableHardwareOAuth { CAT Entra (AAD) Standards TAG - "lowimpact" ADDEDCOMPONENT IMPACT Low Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableLitigationHold.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableLitigationHold.ps1 index cdea9bd134b1..549a0d8b1590 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableLitigationHold.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableLitigationHold.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardEnableLitigationHold { CAT Exchange Standards TAG - "lowimpact" ADDEDCOMPONENT IMPACT Low Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 index decc028041c0..022142a0a3c0 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardEnableMailTips { CAT Exchange Standards TAG - "lowimpact" "CIS" "exo_mailtipsenabled" ADDEDCOMPONENT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 index 6bb48f4cc888..ec82ce508ce8 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardEnableMailboxAuditing { CAT Exchange Standards TAG - "lowimpact" "CIS" "exo_mailboxaudit" ADDEDCOMPONENT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 index 9a28cea18c9c..8c26ecb9ef1e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardEnableOnlineArchiving { CAT Exchange Standards TAG - "lowimpact" ADDEDCOMPONENT IMPACT Low Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnablePronouns.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnablePronouns.ps1 index fda0d9fa90b0..532c133fc736 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnablePronouns.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnablePronouns.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardEnablePronouns { CAT Global Standards TAG - "lowimpact" ADDEDCOMPONENT IMPACT Low Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 index 59f66f0f41c5..4525d093a6e2 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardExternalMFATrusted { CAT Entra (AAD) Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"creatable":false,"label":"Select value","name":"standards.ExternalMFATrusted.state","options":[{"label":"Enabled","value":"true"},{"label":"Disabled","value":"false"}]} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 index 809f1d855d91..652a5ab72466 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardFocusedInbox { CAT Exchange Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.FocusedInbox.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 index a708c8ea6bc9..882ef5efd6c6 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardGlobalQuarantineNotifications { CAT Exchange Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.GlobalQuarantineNotifications.NotificationInterval","options":[{"label":"4 hours","value":"04:00:00"},{"label":"1 day/Daily","value":"1.00:00:00"},{"label":"7 days/Weekly","value":"7.00:00:00"}]} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 index 5cbbd7077d9e..698f42063b2f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 @@ -17,7 +17,7 @@ function Invoke-CIPPStandardGroupTemplate { DISABLEDFEATURES IMPACT - Medium + Medium Impact ADDEDCOMPONENT {"type":"autoComplete","name":"groupTemplate","label":"Select Group Template","api":{"url":"/api/ListGroupTemplates","labelField":"Displayname","valueField":"GUID","queryKey":"ListGroupTemplates"}} UPDATECOMMENTBLOCK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 index 3fd021180a2a..6340b7f3e0d1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardIntuneComplianceSettings { CAT Intune Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.IntuneComplianceSettings.secureByDefault","label":"Mark devices with no compliance policy as","options":[{"label":"Compliant","value":"false"},{"label":"Non-Compliant","value":"true"}]} {"type":"number","name":"standards.IntuneComplianceSettings.deviceComplianceCheckinThresholdDays","label":"Compliance status validity period (days)"} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 index 8f816c3e5207..d31e28678f39 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 @@ -17,7 +17,7 @@ function Invoke-CIPPStandardIntuneTemplate { DISABLEDFEATURES IMPACT - High + High Impact ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"creatable":false,"name":"TemplateList","label":"Select Intune Template","api":{"url":"/api/ListIntuneTemplates","labelField":"Displayname","valueField":"GUID","queryKey":"languages"}} {"name":"AssignTo","label":"Who should this template be assigned to?","type":"radio","options":[{"label":"Do not assign","value":"On"},{"label":"Assign to all users","value":"allLicensedUsers"},{"label":"Assign to all devices","value":"AllDevices"},{"label":"Assign to all users and devices","value":"AllDevicesAndUsers"},{"label":"Assign to Custom Group","value":"customGroup"}]} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMailContacts.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMailContacts.ps1 index 28ad1f65a291..e62f75091cdc 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMailContacts.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMailContacts.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardMailContacts { CAT Global Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"textField","name":"standards.MailContacts.GeneralContact","label":"General Contact","required":false} {"type":"textField","name":"standards.MailContacts.SecurityContact","label":"Security Contact","required":false} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 index e34a7124f8e5..16deab23d1b5 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardMalwareFilterPolicy { CAT Defender Standards TAG - "lowimpact" "CIS" "mdo_zapspam" "mdo_zapphish" diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMessageExpiration.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMessageExpiration.ps1 index 4126811842e8..b79ae37cebe4 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMessageExpiration.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMessageExpiration.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardMessageExpiration { CAT Exchange Standards TAG - "lowimpact" ADDEDCOMPONENT IMPACT Low Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 index 55786b89ae3c..41ca284db346 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardNudgeMFA { CAT Entra (AAD) Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"creatable":false,"label":"Select value","name":"standards.NudgeMFA.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} {"type":"number","name":"standards.NudgeMFA.snoozeDurationInDays","label":"Number of days to allow users to skip registering Authenticator (0-14, default is 1)","default":1} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 index 2bb61266853c..275f4b6dcf03 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardOauthConsent { CAT Entra (AAD) Standards TAG - "mediumimpact" "CIS" ADDEDCOMPONENT {"type":"textField","name":"standards.OauthConsent.AllowedApps","label":"Allowed application IDs, comma separated","required":false} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsentLowSec.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsentLowSec.ps1 index e43a57367058..4573a7875eeb 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsentLowSec.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsentLowSec.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardOauthConsentLowSec { CAT Entra (AAD) Standards TAG - "mediumimpact" "IntegratedApps" IMPACT Medium Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOutBoundSpamAlert.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOutBoundSpamAlert.ps1 index 4c6230c0b28c..695f9f5e7759 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOutBoundSpamAlert.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOutBoundSpamAlert.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardOutBoundSpamAlert { CAT Exchange Standards TAG - "lowimpact" "CIS" ADDEDCOMPONENT {"type":"textField","name":"standards.OutBoundSpamAlert.OutboundSpamContact","label":"Outbound spam contact"} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 index a951163aaf6c..e21c27e1fe7c 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardPWcompanionAppAllowedState { CAT Entra (AAD) Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"creatable":false,"label":"Select value","name":"standards.PWcompanionAppAllowedState.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 index 8ddea0115551..47d4fd1d7fd7 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardPWdisplayAppInformationRequiredState { CAT Entra (AAD) Standards TAG - "lowimpact" "CIS" ADDEDCOMPONENT IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 index 1e1495edb6fb..c629902a52b0 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardPasswordExpireDisabled { CAT Entra (AAD) Standards TAG - "lowimpact" "CIS" "PWAgePolicyNew" ADDEDCOMPONENT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishProtection.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishProtection.ps1 index 4cd025548e72..33670894bd76 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishProtection.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishProtection.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardPhishProtection { CAT Global Standards TAG - "lowimpact" ADDEDCOMPONENT IMPACT Low Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardProfilePhotos.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardProfilePhotos.ps1 index 6cb5c6b0bcb3..0453733541e6 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardProfilePhotos.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardProfilePhotos.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardProfilePhotos { CAT Global Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"creatable":false,"label":"Select value","name":"standards.ProfilePhotos.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 index 3040ef1f155e..e225cd327e9a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardQuarantineRequestAlert { CAT Defender Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"textField","name":"standards.QuarantineRequestAlert.NotifyUser","label":"E-mail to receive the alert"} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 similarity index 80% rename from Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicy.ps1 rename to Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 index 291e21412a92..9aa226928b41 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 @@ -1,86 +1,107 @@ -function Invoke-CIPPStandardRetentionPolicyTag { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) RetentionPolicyTag - #> - - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'RetentionPolicyTag' - - $PolicyName = 'CIPP Deleted Items' - $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-RetentionPolicyTag' | - Where-Object -Property Identity -EQ $PolicyName - - $PolicyState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-RetentionPolicy' | - Where-Object -Property Identity -EQ 'Default MRM Policy' - - $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and - ($CurrentState.RetentionEnabled -eq $true) -and - ($CurrentState.RetentionAction -eq 'PermanentlyDelete') -and - ($CurrentState.AgeLimitForRetention -eq ([timespan]::FromDays($Settings.AgeLimitForRetention))) -and - ($CurrentState.Type -eq 'DeletedItems') -and - ($PolicyState.RetentionPolicyTagLinks -contains $PolicyName) - - if ($Settings.remediate -eq $true) { - - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Retention policy tag already correctly configured' -sev Info - } else { - $cmdparams = @{ - RetentionEnabled = $true - AgeLimitForRetention = $Settings.AgeLimitForRetention - RetentionAction = 'PermanentlyDelete' - } - - if ($CurrentState.Name -eq $PolicyName) { - try { - $cmdparams.Add('Identity', $PolicyName) - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-RetentionPolicyTag' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Retention policy tag $PolicyName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update Retention policy tag $PolicyName." -sev Error -LogData $_ - } - } else { - try { - $cmdparams.Add('Name', $PolicyName) - $cmdparams.Add('Type', 'DeletedItems') - New-ExoRequest -tenantid $Tenant -cmdlet 'New-RetentionPolicyTag' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created Retention policy tag $PolicyName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Retention policy tag $PolicyName." -sev Error -LogData $_ - } - } - - if ($PolicyState.RetentionPolicyTagLinks -notcontains $PolicyName) { - try { - $cmdparams = @{ - Identity = 'Default MRM Policy' - RetentionPolicyTagLinks = @($PolicyState.RetentionPolicyTagLinks + $PolicyName) - } - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-RetentionPolicy' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Added $PolicyName Retention tag to $($PolicyState.Identity)." -sev Info - } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to add $PolicyName Retention tag to $($PolicyState.Identity)." -sev Error -LogData $_.Exception.Message - } - } - - } - - } - - if ($Settings.alert -eq $true) { - - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Retention Policy is enabled' -sev Info - } else { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Retention Policy is not enabled' -sev Alert - } - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'RetentionPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant - } - -} +function Invoke-CIPPStandardRetentionPolicyTag { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) RetentionPolicyTag + .SYNOPSIS + (Label) Retention Policy, permanently delete items in Deleted Items after X days + .DESCRIPTION + (Helptext) Creates a CIPP - Deleted Items retention policy tag that permanently deletes items in the Deleted Items folder after X days. + (DocsDescription) Creates a CIPP - Deleted Items retention policy tag that permanently deletes items in the Deleted Items folder after X days. + .NOTES + CAT + Exchange Standards + TAG + "highimpact" + ADDEDCOMPONENT + {"type":"number","name":"standards.RetentionPolicyTag.AgeLimitForRetention","label":"Retention Days","required":true} + IMPACT + High Impact + POWERSHELLEQUIVALENT + Set-RetentionPolicyTag + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/exchange-standards#high-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'RetentionPolicyTag' + + $PolicyName = 'CIPP Deleted Items' + $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-RetentionPolicyTag' | + Where-Object -Property Identity -EQ $PolicyName + + $PolicyState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-RetentionPolicy' | + Where-Object -Property Identity -EQ 'Default MRM Policy' + + $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and + ($CurrentState.RetentionEnabled -eq $true) -and + ($CurrentState.RetentionAction -eq 'PermanentlyDelete') -and + ($CurrentState.AgeLimitForRetention -eq ([timespan]::FromDays($Settings.AgeLimitForRetention))) -and + ($CurrentState.Type -eq 'DeletedItems') -and + ($PolicyState.RetentionPolicyTagLinks -contains $PolicyName) + + if ($Settings.remediate -eq $true) { + + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Retention policy tag already correctly configured' -sev Info + } else { + $cmdparams = @{ + RetentionEnabled = $true + AgeLimitForRetention = $Settings.AgeLimitForRetention + RetentionAction = 'PermanentlyDelete' + } + + if ($CurrentState.Name -eq $PolicyName) { + try { + $cmdparams.Add('Identity', $PolicyName) + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-RetentionPolicyTag' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Retention policy tag $PolicyName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update Retention policy tag $PolicyName." -sev Error -LogData $_ + } + } else { + try { + $cmdparams.Add('Name', $PolicyName) + $cmdparams.Add('Type', 'DeletedItems') + New-ExoRequest -tenantid $Tenant -cmdlet 'New-RetentionPolicyTag' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created Retention policy tag $PolicyName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Retention policy tag $PolicyName." -sev Error -LogData $_ + } + } + + if ($PolicyState.RetentionPolicyTagLinks -notcontains $PolicyName) { + try { + $cmdparams = @{ + Identity = 'Default MRM Policy' + RetentionPolicyTagLinks = @($PolicyState.RetentionPolicyTagLinks + $PolicyName) + } + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-RetentionPolicy' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Added $PolicyName Retention tag to $($PolicyState.Identity)." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to add $PolicyName Retention tag to $($PolicyState.Identity)." -sev Error -LogData $_.Exception.Message + } + } + + } + + } + + if ($Settings.alert -eq $true) { + + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Retention Policy is enabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Retention Policy is not enabled' -sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'RetentionPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant + } + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 index a89fd5d877b8..71dd3abde10f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardRotateDKIM { CAT Exchange Standards TAG - "lowimpact" "CIS" ADDEDCOMPONENT IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPAzureB2B.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPAzureB2B.ps1 index bd016f0f9ba8..63a6e0d431cb 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPAzureB2B.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPAzureB2B.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardSPAzureB2B { CAT SharePoint Standards TAG - "lowimpact" "CIS" ADDEDCOMPONENT IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDirectSharing.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDirectSharing.ps1 index bd20bff087ac..ba1d39eef96e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDirectSharing.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDirectSharing.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardSPDirectSharing { CAT SharePoint Standards TAG - "mediumimpact" "CIS" ADDEDCOMPONENT IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisableLegacyWorkflows.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisableLegacyWorkflows.ps1 index 7ee1f747340b..7dd4ab37ffa1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisableLegacyWorkflows.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisableLegacyWorkflows.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardSPDisableLegacyWorkflows { CAT SharePoint Standards TAG - "lowimpact" ADDEDCOMPONENT IMPACT Low Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisallowInfectedFiles.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisallowInfectedFiles.ps1 index f6529c0980f4..0f2c2ecead49 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisallowInfectedFiles.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisallowInfectedFiles.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardSPDisallowInfectedFiles { CAT SharePoint Standards TAG - "lowimpact" "CIS" ADDEDCOMPONENT IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 index 8e07f8e0ff24..28276672d6c3 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardSPExternalUserExpiration { CAT SharePoint Standards TAG - "mediumimpact" "CIS" ADDEDCOMPONENT {"type":"number","name":"standards.SPExternalUserExpiration.Days","label":"Days until expiration (Default 60)"} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 index 4f6dda4c235d..32799e32d5b0 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardSafeAttachmentPolicy { CAT Defender Standards TAG - "lowimpact" "CIS" "mdo_safedocuments" "mdo_commonattachmentsfilter" diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 index b9b9823cf47c..830fc109a688 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardSafeLinksPolicy { CAT Defender Standards TAG - "lowimpact" "CIS" "mdo_safelinksforemail" "mdo_safelinksforOfficeApps" diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 index a2ce48171f59..a3973401f009 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardSendReceiveLimitTenant { CAT Exchange Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"number","name":"standards.SendReceiveLimitTenant.SendLimit","label":"Send limit in MB (Default is 35)","default":35} {"type":"number","name":"standards.SendReceiveLimitTenant.ReceiveLimit","label":"Receive Limit in MB (Default is 36)","default":36} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 index 167cc6a3d1b1..e6958b9e686e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardSpoofWarn { CAT Exchange Standards TAG - "lowimpact" "CIS" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.SpoofWarn.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 index 7d0faafb3cf1..31b1afda1e09 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardStaleEntraDevices { CAT Entra (AAD) Standards TAG - "highimpact" "CIS" ADDEDCOMPONENT {"type":"number","name":"standards.StaleEntraDevices.deviceAgeThreshold","label":"Days before stale(Dont set below 30)"} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTAP.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTAP.ps1 index 3ec0236edce4..7800b55045bb 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTAP.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTAP.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardTAP { CAT Entra (AAD) Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"creatable":false,"label":"Select TAP Lifetime","name":"standards.TAP.config","options":[{"label":"Only Once","value":"true"},{"label":"Multiple Logons","value":"false"}]} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEmailIntegration.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEmailIntegration.ps1 index d5a1a5db6b41..5aec26f2c951 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEmailIntegration.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEmailIntegration.ps1 @@ -13,7 +13,6 @@ Function Invoke-CIPPStandardTeamsEmailIntegration { CAT Teams Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"switch","name":"standards.TeamsEmailIntegration.AllowEmailIntoChannel","label":"Allow channel emails"} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEnrollUser.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEnrollUser.ps1 index 7d8677312a95..77d3aa8258b6 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEnrollUser.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEnrollUser.ps1 @@ -13,7 +13,6 @@ Function Invoke-CIPPStandardTeamsEnrollUser { CAT Teams Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.TeamsEnrollUser.EnrollUserOverride","label":"Voice and Face Enrollment","options":[{"label":"Disabled","value":"Disabled"},{"label":"Enabled","value":"Enabled"}]} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalFileSharing.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalFileSharing.ps1 index 1fc934983092..dbde0768fccd 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalFileSharing.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalFileSharing.ps1 @@ -13,7 +13,6 @@ Function Invoke-CIPPStandardTeamsExternalFileSharing { CAT Teams Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"switch","name":"standards.TeamsExternalFileSharing.AllowGoogleDrive","label":"Allow Google Drive"} {"type":"switch","name":"standards.TeamsExternalFileSharing.AllowShareFile","label":"Allow ShareFile"} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 index 6ea500719d57..e6c956d61808 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 @@ -13,7 +13,6 @@ Function Invoke-CIPPStandardTeamsGlobalMeetingPolicy { CAT Teams Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.TeamsGlobalMeetingPolicy.DesignatedPresenterRoleMode","label":"Default value of the `Who can present?`","options":[{"label":"EveryoneUserOverride","value":"EveryoneUserOverride"},{"label":"EveryoneInCompanyUserOverride","value":"EveryoneInCompanyUserOverride"},{"label":"EveryoneInSameAndFederatedCompanyUserOverride","value":"EveryoneInSameAndFederatedCompanyUserOverride"},{"label":"OrganizerOnlyUserOverride","value":"OrganizerOnlyUserOverride"}]} {"type":"switch","name":"standards.TeamsGlobalMeetingPolicy.AllowAnonymousUsersToJoinMeeting","label":"Allow anonymous users to join meeting"} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 index e2adde819c8a..9a3f94bb450f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardTeamsMeetingsByDefault { CAT Exchange Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.TeamsMeetingsByDefault.state","options":[{"label":"Enabled","value":"true"},{"label":"Disabled","value":"false"}]} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 index 9cd86647571e..5a6c9c956c1d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardTenantDefaultTimezone { CAT SharePoint Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"TimezoneSelect","name":"standards.TenantDefaultTimezone.Timezone","label":"Timezone"} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 index d5d3bb1e22f9..89fb1db0b725 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 @@ -15,7 +15,7 @@ function Invoke-CIPPStandardTransportRuleTemplate { DISABLEDFEATURES IMPACT - Medium + Medium Impact ADDEDCOMPONENT {"type":"autoComplete","name":"transportRuleTemplate","label":"Select Transport Rule Template","api":{"url":"/api/ListTransportRulesTemplates","labelField":"name","valueField":"GUID","queryKey":"ListTransportRulesTemplates"}} UPDATECOMMENTBLOCK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOAuthTokens.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOAuthTokens.ps1 index b621e3e85ea6..f335ba4859e1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOAuthTokens.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOAuthTokens.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardallowOAuthTokens { CAT Entra (AAD) Standards TAG - "lowimpact" ADDEDCOMPONENT IMPACT Low Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOTPTokens.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOTPTokens.ps1 index fb07572ffb32..a79bbd62a2e4 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOTPTokens.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOTPTokens.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardallowOTPTokens { CAT Entra (AAD) Standards TAG - "lowimpact" ADDEDCOMPONENT IMPACT Low Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 index fe46ed9e9d44..dfac16a43399 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardcalDefault { CAT Exchange Standards TAG - "lowimpact" DISABLEDFEATURES ADDEDCOMPONENT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneBrandingProfile.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneBrandingProfile.ps1 index 420f3c11498f..95289a2fa964 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneBrandingProfile.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneBrandingProfile.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardintuneBrandingProfile { CAT Intune Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"textField","name":"standards.intuneBrandingProfile.displayName","label":"Organization name","required":false} {"type":"switch","name":"standards.intuneBrandingProfile.showLogo","label":"Show logo"} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 index cc955e92a9a5..34ac3bb23102 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardintuneDeviceRetirementDays { CAT Intune Standards TAG - "lowimpact" ADDEDCOMPONENT {"type":"number","name":"standards.intuneDeviceRetirementDays.days","label":"Maximum days (0 equals disabled)"} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardlaps.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardlaps.ps1 index 4229ea55dd68..9b30858e3675 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardlaps.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardlaps.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardlaps { CAT Entra (AAD) Standards TAG - "lowimpact" ADDEDCOMPONENT IMPACT Low Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 index 4faae11a6f95..7a4e443d7962 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardsharingCapability { CAT SharePoint Standards TAG - "highimpact" "CIS" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"label":"Select Sharing Level","name":"standards.sharingCapability.Level","options":[{"label":"Users can share only with people in the organization. No external sharing is allowed.","value":"disabled"},{"label":"Users can share with new and existing guests. Guests must sign in or provide a verification code.","value":"externalUserSharingOnly"},{"label":"Users can share with anyone by using links that do not require sign-in.","value":"externalUserAndGuestSharing"},{"label":"Users can share with existing guests (those already in the directory of the organization).","value":"existingExternalUserSharingOnly"}]} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingDomainRestriction.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingDomainRestriction.ps1 index 0b736f730720..32b74e3b1780 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingDomainRestriction.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingDomainRestriction.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardsharingDomainRestriction { CAT SharePoint Standards TAG - "highimpact" "CIS" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"name":"standards.sharingDomainRestriction.Mode","label":"Limit external sharing by domains","options":[{"label":"Off","value":"none"},{"label":"Restrict sharing to specific domains","value":"allowList"},{"label":"Block sharing to specific domains","value":"blockList"}]} From 00a333d9f5e0c986a74ebf9550c5e9a8de1c39cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sat, 15 Feb 2025 13:13:01 +0100 Subject: [PATCH 004/167] Casing and better error logging --- .../Invoke-CIPPStandardRetentionPolicyTag.ps1 | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 index 9aa226928b41..3d61a42dd80f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 @@ -37,7 +37,7 @@ function Invoke-CIPPStandardRetentionPolicyTag { $PolicyState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-RetentionPolicy' | Where-Object -Property Identity -EQ 'Default MRM Policy' - $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and + $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and ($CurrentState.RetentionEnabled -eq $true) -and ($CurrentState.RetentionAction -eq 'PermanentlyDelete') -and ($CurrentState.AgeLimitForRetention -eq ([timespan]::FromDays($Settings.AgeLimitForRetention))) -and @@ -45,45 +45,50 @@ function Invoke-CIPPStandardRetentionPolicyTag { ($PolicyState.RetentionPolicyTagLinks -contains $PolicyName) if ($Settings.remediate -eq $true) { + Write-Host 'Time to remediate' if ($StateIsCorrect -eq $true) { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Retention policy tag already correctly configured' -sev Info } else { - $cmdparams = @{ + $cmdParams = @{ RetentionEnabled = $true AgeLimitForRetention = $Settings.AgeLimitForRetention - RetentionAction = 'PermanentlyDelete' + RetentionAction = 'PermanentlyDelete' } if ($CurrentState.Name -eq $PolicyName) { try { - $cmdparams.Add('Identity', $PolicyName) - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-RetentionPolicyTag' -cmdparams $cmdparams -UseSystemMailbox $true + $cmdParams.Add('Identity', $PolicyName) + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-RetentionPolicyTag' -cmdParams $cmdParams -UseSystemMailbox $true Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Retention policy tag $PolicyName." -sev Info } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update Retention policy tag $PolicyName." -sev Error -LogData $_ + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update Retention policy tag $PolicyName." -sev Error -LogData $ErrorMessage } } else { try { - $cmdparams.Add('Name', $PolicyName) - $cmdparams.Add('Type', 'DeletedItems') - New-ExoRequest -tenantid $Tenant -cmdlet 'New-RetentionPolicyTag' -cmdparams $cmdparams -UseSystemMailbox $true + $cmdParams.Add('Name', $PolicyName) + $cmdParams.Add('Type', 'DeletedItems') + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'New-RetentionPolicyTag' -cmdParams $cmdParams -UseSystemMailbox $true Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created Retention policy tag $PolicyName." -sev Info } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Retention policy tag $PolicyName." -sev Error -LogData $_ + + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Retention policy tag $PolicyName." -sev Error -LogData $ErrorMessage } } if ($PolicyState.RetentionPolicyTagLinks -notcontains $PolicyName) { try { - $cmdparams = @{ - Identity = 'Default MRM Policy' + $cmdParams = @{ + Identity = 'Default MRM Policy' RetentionPolicyTagLinks = @($PolicyState.RetentionPolicyTagLinks + $PolicyName) } - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-RetentionPolicy' -cmdparams $cmdparams -UseSystemMailbox $true + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-RetentionPolicy' -cmdParams $cmdParams -UseSystemMailbox $true Write-LogMessage -API 'Standards' -tenant $Tenant -message "Added $PolicyName Retention tag to $($PolicyState.Identity)." -sev Info } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to add $PolicyName Retention tag to $($PolicyState.Identity)." -sev Error -LogData $_.Exception.Message + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to add $PolicyName Retention tag to $($PolicyState.Identity)." -sev Error -LogData $ErrorMessage } } From 670c2bbc86036f657fbb742c6e7a3969611d88b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sat, 15 Feb 2025 13:23:34 +0100 Subject: [PATCH 005/167] last time for sure --- .../CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 | 1 - .../Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardDisableEmail.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardDisableGuests.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardDisableQRCodePin.ps1 | 1 - .../CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSMS.ps1 | 1 - .../Standards/Invoke-CIPPStandardDisableSecurityGroupUsers.ps1 | 1 - .../Standards/Invoke-CIPPStandardDisableSelfServiceLicenses.ps1 | 1 - .../Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardDisableVoice.ps1 | 1 - .../Standards/Invoke-CIPPStandardDisablex509Certificate.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 | 1 - .../CIPPCore/Public/Standards/Invoke-CIPPStandardGuestInvite.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardLegacyMFACleanup.ps1 | 1 - .../CIPPCore/Public/Standards/Invoke-CIPPStandardPerUserMFA.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardSPEmailAttestation.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardSPSyncButtonState.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardSecurityDefaults.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 | 1 - .../Standards/Invoke-CIPPStandardTeamsExternalAccessPolicy.ps1 | 1 - .../Invoke-CIPPStandardTeamsFederationConfiguration.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 | 1 - .../CIPPCore/Public/Standards/Invoke-CIPPStandardUndoOauth.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 | 1 - .../Public/Standards/Invoke-CIPPStandardunmanagedSync.ps1 | 1 - 34 files changed, 34 deletions(-) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 index b1f5e7fece95..94c7890adacf 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardBookings { CAT Exchange Standards TAG - "mediumimpact" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.Bookings.state","options":[{"label":"Enabled","value":"true"},{"label":"Disabled","value":"false"}]} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 index 2132294d31ca..a1c724a7167d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDelegateSentItems { CAT Exchange Standards TAG - "mediumimpact" ADDEDCOMPONENT {"type":"switch","label":"Include user mailboxes","name":"standards.DelegateSentItems.IncludeUserMailboxes"} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 index 3ac6d6d19897..f488fd9e1e94 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableAddShortcutsToOneDrive { CAT SharePoint Standards TAG - "mediumimpact" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"creatable":false,"label":"Add Shortcuts To OneDrive button state","name":"standards.DisableAddShortcutsToOneDrive.state","options":[{"label":"Disabled","value":"true"},{"label":"Enabled","value":"false"}]} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 index 99ada42f790d..eb4de11a619a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableBasicAuthSMTP { CAT Global Standards TAG - "mediumimpact" ADDEDCOMPONENT IMPACT Medium Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableEmail.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableEmail.ps1 index 42ae78c7a734..b810f67f6c82 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableEmail.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableEmail.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableEmail { CAT Entra (AAD) Standards TAG - "highimpact" ADDEDCOMPONENT IMPACT High Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuests.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuests.ps1 index e7d070a4fbae..b17a84ee81f3 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuests.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuests.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableGuests { CAT Entra (AAD) Standards TAG - "mediumimpact" ADDEDCOMPONENT IMPACT Medium Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableQRCodePin.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableQRCodePin.ps1 index 98c05fc3c90e..ae8b46922a0a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableQRCodePin.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableQRCodePin.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableQRCodePin { CAT Entra (AAD) Standards TAG - "highimpact" ADDEDCOMPONENT IMPACT High Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSMS.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSMS.ps1 index 2b3c2764f1e1..5c79181d7879 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSMS.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSMS.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableSMS { CAT Entra (AAD) Standards TAG - "highimpact" ADDEDCOMPONENT IMPACT High Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSecurityGroupUsers.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSecurityGroupUsers.ps1 index 55fa4af4371d..8f8643dacadc 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSecurityGroupUsers.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSecurityGroupUsers.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableSecurityGroupUsers { CAT Entra (AAD) Standards TAG - "mediumimpact" ADDEDCOMPONENT IMPACT Medium Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSelfServiceLicenses.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSelfServiceLicenses.ps1 index 4567b9d99a72..64eab6788d6a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSelfServiceLicenses.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSelfServiceLicenses.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableSelfServiceLicenses { CAT Entra (AAD) Standards TAG - "mediumimpact" ADDEDCOMPONENT {"type":"textField","name":"standards.DisableSelfServiceLicenses.Exclusions","label":"License Ids to exclude from this standard","required":false} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 index b61bf1529281..442a48ad6c2f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableUserSiteCreate { CAT SharePoint Standards TAG - "highimpact" ADDEDCOMPONENT IMPACT High Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableVoice.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableVoice.ps1 index 907326273211..db80a2e91e8e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableVoice.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableVoice.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisableVoice { CAT Entra (AAD) Standards TAG - "highimpact" ADDEDCOMPONENT IMPACT High Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisablex509Certificate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisablex509Certificate.ps1 index 9c3ab1093e0f..d6fcb84c2d08 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisablex509Certificate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisablex509Certificate.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardDisablex509Certificate { CAT Entra (AAD) Standards TAG - "highimpact" ADDEDCOMPONENT IMPACT High Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 index 4f1e011bb007..c2b6154f2d99 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardExcludedfileExt { CAT SharePoint Standards TAG - "highimpact" ADDEDCOMPONENT {"type":"textField","name":"standards.ExcludedfileExt.ext","label":"Extensions, Comma separated"} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGuestInvite.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGuestInvite.ps1 index 6ffdc6aab406..cb3d745d17e5 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGuestInvite.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGuestInvite.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardGuestInvite { CAT Entra (AAD) Standards TAG - "mediumimpact" ADDEDCOMPONENT {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Who can send invites?","name":"standards.GuestInvite.allowInvitesFrom","options":[{"label":"Everyone","value":"everyone"},{"label":"Admins, Guest inviters and All Members","value":"adminsGuestInvitersAndAllMembers"},{"label":"Admins and Guest inviters","value":"adminsAndGuestInviters"},{"label":"None","value":"none"}]} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardLegacyMFACleanup.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardLegacyMFACleanup.ps1 index 01278dcb65db..5715f6f16b9d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardLegacyMFACleanup.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardLegacyMFACleanup.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardLegacyMFACleanup { CAT Entra (AAD) Standards TAG - "mediumimpact" ADDEDCOMPONENT IMPACT Medium Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPerUserMFA.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPerUserMFA.ps1 index 21a802bc079c..8df7ac45f4e5 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPerUserMFA.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPerUserMFA.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardPerUserMFA { CAT Entra (AAD) Standards TAG - "highimpact" ADDEDCOMPONENT IMPACT High Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 index 3d61a42dd80f..2e749da720f2 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardRetentionPolicyTag { CAT Exchange Standards TAG - "highimpact" ADDEDCOMPONENT {"type":"number","name":"standards.RetentionPolicyTag.AgeLimitForRetention","label":"Retention Days","required":true} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPEmailAttestation.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPEmailAttestation.ps1 index 395bdd3ee208..0170bd7286cc 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPEmailAttestation.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPEmailAttestation.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardSPEmailAttestation { CAT SharePoint Standards TAG - "mediumimpact" "CIS" ADDEDCOMPONENT {"type":"number","name":"standards.SPEmailAttestation.Days","label":"Require re-authentication every X Days (Default 15)"} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPSyncButtonState.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPSyncButtonState.ps1 index c3da574978b3..03b66cfe0c3e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPSyncButtonState.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPSyncButtonState.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardSPSyncButtonState { CAT SharePoint Standards TAG - "mediumimpact" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"creatable":false,"label":"SharePoint Sync Button state","name":"standards.SPSyncButtonState.state","options":[{"label":"Disabled","value":"true"},{"label":"Enabled","value":"false"}]} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 index 7d67aa1471fe..cc20e9cd1950 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardSafeSendersDisable { CAT Exchange Standards TAG - "mediumimpact" ADDEDCOMPONENT DISABLEDFEATURES diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSecurityDefaults.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSecurityDefaults.ps1 index 3a43c05d0222..1086d7bc1be8 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSecurityDefaults.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSecurityDefaults.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardSecurityDefaults { CAT Entra (AAD) Standards TAG - "highimpact" ADDEDCOMPONENT IMPACT High Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 index b6b8eae02516..df66513ff40c 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardSendFromAlias { CAT Exchange Standards TAG - "mediumimpact" ADDEDCOMPONENT IMPACT Medium Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 index 7204975387ad..6eec8093a260 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardShortenMeetings { CAT Exchange Standards TAG - "mediumimpact" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.ShortenMeetings.ShortenEventScopeDefault","options":[{"label":"Disabled/None","value":"None"},{"label":"End early","value":"EndEarly"},{"label":"Start late","value":"StartLate"}]} {"type":"number","name":"standards.ShortenMeetings.DefaultMinutesToReduceShortEventsBy","label":"Minutes to reduce short calendar events by (Default is 5)","default":5} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 index 539024fd842f..953c72248cf9 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardSpamFilterPolicy { CAT Defender Standards TAG - "mediumimpact" ADDEDCOMPONENT {"type":"number","label":"Bulk email threshold (Default 7)","name":"standards.SpamFilterPolicy.BulkThreshold","default":7} {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Spam Action","name":"standards.SpamFilterPolicy.SpamAction","options":[{"label":"Quarantine the message","value":"Quarantine"},{"label":"Move message to Junk Email folder","value":"MoveToJmf"}]} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalAccessPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalAccessPolicy.ps1 index 3c79a6fd30be..77215de033b1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalAccessPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalAccessPolicy.ps1 @@ -13,7 +13,6 @@ Function Invoke-CIPPStandardTeamsExternalAccessPolicy { CAT Teams Standards TAG - "mediumimpact" ADDEDCOMPONENT {"type":"switch","name":"standards.TeamsExternalAccessPolicy.EnableFederationAccess","label":"Allow communication from trusted organizations"} {"type":"switch","name":"standards.TeamsExternalAccessPolicy.EnablePublicCloudAccess","label":"Allow user to communicate with Skype users"} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 index 8d1c8d84270d..0f191dd0149d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 @@ -13,7 +13,6 @@ Function Invoke-CIPPStandardTeamsFederationConfiguration { CAT Teams Standards TAG - "mediumimpact" ADDEDCOMPONENT {"type":"switch","name":"standards.TeamsFederationConfiguration.AllowTeamsConsumer","label":"Allow users to communicate with other organizations"} {"type":"switch","name":"standards.TeamsFederationConfiguration.AllowPublicUsers","label":"Allow users to communicate with Skype Users"} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 index afda1581bf25..56b13d7d967f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 @@ -13,7 +13,6 @@ Function Invoke-CIPPStandardTeamsMessagingPolicy { CAT Teams Standards TAG - "mediumimpact" ADDEDCOMPONENT {"type":"switch","name":"standards.TeamsMessagingPolicy.AllowOwnerDeleteMessage","label":"Allow Owner to Delete Messages","default":false} {"type":"switch","name":"standards.TeamsMessagingPolicy.AllowUserDeleteMessage","label":"Allow User to Delete Messages","default":true} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUndoOauth.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUndoOauth.ps1 index 333de3e01992..4eb46340bfe1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUndoOauth.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUndoOauth.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardUndoOauth { CAT Entra (AAD) Standards TAG - "highimpact" ADDEDCOMPONENT IMPACT High Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 index 6f2ab4f113d0..ff74e6a0bda4 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardUserSubmissions { CAT Exchange Standards TAG - "mediumimpact" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.UserSubmissions.state","options":[{"label":"Enabled","value":"enable"},{"label":"Disabled","value":"disable"}]} {"type":"textField","name":"standards.UserSubmissions.email","required":false,"label":"Destination email address"} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 index 1f1f03b645d5..50c59494e277 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandarddisableMacSync { CAT SharePoint Standards TAG - "highimpact" ADDEDCOMPONENT IMPACT High Impact diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 index aec44ee5a39c..2103a785915e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardintuneDeviceReg { CAT Intune Standards TAG - "mediumimpact" ADDEDCOMPONENT {"type":"number","name":"standards.intuneDeviceReg.max","label":"Maximum devices (Enter 2147483647 for unlimited.)","required":true} IMPACT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 index 9939dd0005c6..26e60d4930d5 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardintuneRequireMFA { CAT Intune Standards TAG - "mediumimpact" IMPACT Medium Impact POWERSHELLEQUIVALENT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardunmanagedSync.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardunmanagedSync.ps1 index c659ba14750b..15547c8893ce 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardunmanagedSync.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardunmanagedSync.ps1 @@ -13,7 +13,6 @@ function Invoke-CIPPStandardunmanagedSync { CAT SharePoint Standards TAG - "highimpact" ADDEDCOMPONENT IMPACT High Impact From 7a1b04adb1dda6bb98ee61f557ae98e4e2b37d58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sat, 15 Feb 2025 14:17:04 +0100 Subject: [PATCH 006/167] New standard: AntiSpamSafeList https://github.com/KelvinTegelaar/CIPP/issues/2943 --- .../Invoke-CIPPStandardAntiSpamSafeList.ps1 | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiSpamSafeList.ps1 diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiSpamSafeList.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiSpamSafeList.ps1 new file mode 100644 index 000000000000..3b8efcb89dde --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiSpamSafeList.ps1 @@ -0,0 +1,76 @@ +function Invoke-CIPPStandardAntiSpamSafeList { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) AntiSpamSafeList + .SYNOPSIS + (Label) Enable Anti-Spam Connection Filter Safe List + .DESCRIPTION + (Helptext) Enables the anti-spam connection filter policy option 'safe list' in Defender. + (DocsDescription) Enables Microsoft's built-in 'safe list' in the anti-spam connection filter policy, rather than setting a custom safe/block list of IPs. + .NOTES + CAT + Defender Standards + TAG + ADDEDCOMPONENT + {"type":"switch","name":"standards.AntiSpamSafeList.EnableSafeList","label":"Enable Safe List"} + IMPACT + Low Impact + POWERSHELLEQUIVALENT + Set-HostedConnectionFilterPolicy "Default" -EnableSafeList $true + RECOMMENDEDBY + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/defender-standards#low-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'AntiSpamSafeList' + + try { + $State = [System.Convert]::ToBoolean($Settings.EnableSafeList) + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'AntiSpamSafeList: Failed to convert the EnableSafeList parameter to a boolean' -sev Error + Return + } + + try { + $CurrentState = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-HostedConnectionFilterPolicy' -cmdParams @{Identity = 'Default' }).EnableSafeList + } catch { + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to get the Anti-Spam Connection Filter Safe List. Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage + Return + } + $WantedState = $State -eq $true ? $true : $false + $StateIsCorrect = if ($CurrentState -eq $WantedState) { $true } else { $false } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'AntiSpamSafeList' -FieldValue $CurrentState -StoreAs bool -Tenant $Tenant + } + + if ($Settings.remediate -eq $true) { + Write-Host 'Time to remediate' + if ($StateIsCorrect -eq $false) { + try { + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-HostedConnectionFilterPolicy' -cmdParams @{ + Identity = 'Default' + EnableSafeList = $WantedState + } + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Successfully set the Anti-Spam Connection Filter Safe List to $WantedState" -sev Info + } catch { + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set the Anti-Spam Connection Filter Safe List to $WantedState. Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage + } + } else { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "The Anti-Spam Connection Filter Safe List is already set correctly to $WantedState" -sev Info + } + } + + if ($Settings.alert -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "The Anti-Spam Connection Filter Safe List is set correctly to $WantedState" -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "The Anti-Spam Connection Filter Safe List is not set correctly to $WantedState" -sev Alert + } + } +} From 38073c695993098b54e6c8b76e606f0a02eac56e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sat, 15 Feb 2025 14:17:45 +0100 Subject: [PATCH 007/167] Forgot the docs comment --- .../Invoke-CIPPStandardAntiSpamSafeList.ps1 | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiSpamSafeList.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiSpamSafeList.ps1 index 3b8efcb89dde..077877e36b32 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiSpamSafeList.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiSpamSafeList.ps1 @@ -5,10 +5,10 @@ function Invoke-CIPPStandardAntiSpamSafeList { .COMPONENT (APIName) AntiSpamSafeList .SYNOPSIS - (Label) Enable Anti-Spam Connection Filter Safe List + (Label) Set Anti-Spam Connection Filter Safe List .DESCRIPTION - (Helptext) Enables the anti-spam connection filter policy option 'safe list' in Defender. - (DocsDescription) Enables Microsoft's built-in 'safe list' in the anti-spam connection filter policy, rather than setting a custom safe/block list of IPs. + (Helptext) Sets the anti-spam connection filter policy option 'safe list' in Defender. + (DocsDescription) Sets [Microsoft's built-in 'safe list'](https://learn.microsoft.com/en-us/powershell/module/exchange/set-hostedconnectionfilterpolicy?view=exchange-ps#-enablesafelist) in the anti-spam connection filter policy, rather than setting a custom safe/block list of IPs. .NOTES CAT Defender Standards @@ -16,12 +16,14 @@ function Invoke-CIPPStandardAntiSpamSafeList { ADDEDCOMPONENT {"type":"switch","name":"standards.AntiSpamSafeList.EnableSafeList","label":"Enable Safe List"} IMPACT - Low Impact + Medium Impact POWERSHELLEQUIVALENT - Set-HostedConnectionFilterPolicy "Default" -EnableSafeList $true + Set-HostedConnectionFilterPolicy "Default" -EnableSafeList \$true RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/defender-standards#low-impact + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/defender-standards#medium-impact #> param($Tenant, $Settings) From 7f19c2a4d5803a3b655ba19edf3566a24a48abf3 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 17 Feb 2025 11:41:14 -0800 Subject: [PATCH 008/167] move metadata change after query execution --- .../HTTP Functions/CIPP/Core/Invoke-ListGraphRequest.ps1 | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListGraphRequest.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListGraphRequest.ps1 index 09beb0a109e2..d50178e4f6ab 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListGraphRequest.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListGraphRequest.ps1 @@ -117,9 +117,6 @@ function Invoke-ListGraphRequest { } $Metadata = $GraphRequestParams - if ($Request.Headers.'x-ms-coldstart' -eq 1) { - $Metadata.ColdStart = $true - } try { $Results = Get-GraphRequestList @GraphRequestParams @@ -142,6 +139,11 @@ function Invoke-ListGraphRequest { $Results = @() } } + + if ($Request.Headers.'x-ms-coldstart' -eq 1) { + $Metadata.ColdStart = $true + } + $GraphRequestData = [PSCustomObject]@{ Results = @($Results) Metadata = $Metadata From 65354e827b79f3e73c1096338a10049089106bc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 17 Feb 2025 18:20:47 +0100 Subject: [PATCH 009/167] Change to POST --- .../Invoke-ExecConverttoRoomMailbox.ps1 | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConverttoRoomMailbox.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConverttoRoomMailbox.ps1 index 0631d7afa78a..f6534c44d310 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConverttoRoomMailbox.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConverttoRoomMailbox.ps1 @@ -11,20 +11,18 @@ Function Invoke-ExecConvertToRoomMailbox { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $User = $Request.Headers - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + Write-LogMessage -Headers $Request.Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' # Interact with query parameters or the body of the request. + $UserID = $Request.Query.ID ?? $Request.Body.ID + Try { - $ConvertedMailbox = Set-CIPPMailboxType -userid $Request.query.id -tenantFilter $Request.query.TenantFilter -APIName $APINAME -Headers $User -MailboxType 'Room' + $ConvertedMailbox = Set-CIPPMailboxType -UserID $UserID -TenantFilter $TenantFilter -APIName $APIName -Headers $Request.Headers -MailboxType 'Room' $Results = [pscustomobject]@{'Results' = "$ConvertedMailbox" } $StatusCode = [HttpStatusCode]::OK } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - $Results = [pscustomobject]@{'Results' = "Failed to convert $($request.query.id) - $ErrorMessage" } + $Results = [pscustomobject]@{'Results' = "$($_.Exception.Message)" } $StatusCode = [HttpStatusCode]::Forbidden } # Associate values to output bindings by calling 'Push-OutputBinding'. From 3bde9385e73e8a6c49042a14f1b2e2822c1bdb5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 17 Feb 2025 18:21:06 +0100 Subject: [PATCH 010/167] Refactor Set-CIPPMailboxType function to use consistent parameter casing and improve message handling dont throw cause it break stuff if it fails fix typo --- .../Invoke-ExecConverttoRoomMailbox.ps1 | 7 +++++-- Modules/CIPPCore/Public/Remove-CIPPUser.ps1 | 7 ++++--- .../CIPPCore/Public/Set-CIPPMailboxType.ps1 | 20 ++++++++++--------- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConverttoRoomMailbox.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConverttoRoomMailbox.ps1 index f6534c44d310..e67d20942705 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConverttoRoomMailbox.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConverttoRoomMailbox.ps1 @@ -19,11 +19,14 @@ Function Invoke-ExecConvertToRoomMailbox { Try { $ConvertedMailbox = Set-CIPPMailboxType -UserID $UserID -TenantFilter $TenantFilter -APIName $APIName -Headers $Request.Headers -MailboxType 'Room' + if ($ConvertedMailbox -like 'Could not convert*') { throw $ConvertedMailbox } $Results = [pscustomobject]@{'Results' = "$ConvertedMailbox" } $StatusCode = [HttpStatusCode]::OK } catch { - $Results = [pscustomobject]@{'Results' = "$($_.Exception.Message)" } - $StatusCode = [HttpStatusCode]::Forbidden + $ErrorMessage = $_.Exception.Message + Write-LogMessage -Headers $Request.Headers -API $APIName -message "Error converting mailbox: $ErrorMessage" -Sev 'Error' + $Results = [pscustomobject]@{'Results' = "$ErrorMessage" } + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ diff --git a/Modules/CIPPCore/Public/Remove-CIPPUser.ps1 b/Modules/CIPPCore/Public/Remove-CIPPUser.ps1 index b789f5943fc5..d892e9421227 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPUser.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPUser.ps1 @@ -10,13 +10,14 @@ function Remove-CIPPUser { try { $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($userid)" -type DELETE -tenant $TenantFilter - Write-LogMessage -headers $Headers, -API $APIName -message "Deleted account $username" -Sev 'Info' -tenant $TenantFilter + Write-LogMessage -headers $Headers -API $APIName -message "Deleted account $username" -Sev 'Info' -tenant $TenantFilter return "Deleted the user account $username" } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers, -API $APIName -message "Could not delete $username. Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - return "Could not delete $username. Error: $($ErrorMessage.NormalizedError)" + $Message = "Could not delete $username. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + return $Message } } diff --git a/Modules/CIPPCore/Public/Set-CIPPMailboxType.ps1 b/Modules/CIPPCore/Public/Set-CIPPMailboxType.ps1 index cd2ba3313635..60f9a6fb4fbf 100644 --- a/Modules/CIPPCore/Public/Set-CIPPMailboxType.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPMailboxType.ps1 @@ -2,22 +2,24 @@ function Set-CIPPMailboxType { [CmdletBinding()] param ( $Headers, - $userid, - $username, + $UserID, + $Username, $APIName = 'Mailbox Conversion', $TenantFilter, - [Parameter()] + [Parameter(Mandatory = $true)] [ValidateSet('Shared', 'Regular', 'Room', 'Equipment')]$MailboxType ) try { - if ([string]::IsNullOrWhiteSpace($username)) { $username = $userid } - $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Set-Mailbox' -cmdParams @{Identity = $userid; Type = $MailboxType } -Anchor $username - Write-LogMessage -headers $Headers -API $APIName -message "Converted $($username) to a $MailboxType mailbox" -Sev 'Info' -tenant $TenantFilter - return "Converted $username to a $MailboxType mailbox" + if ([string]::IsNullOrWhiteSpace($Username)) { $Username = $UserID } + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Set-Mailbox' -cmdParams @{Identity = $UserID; Type = $MailboxType } -Anchor $Username + $Message = "Converted $Username to a $MailboxType mailbox" + Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Info' -tenant $TenantFilter + return $Message } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers -API $APIName -message "Could not convert $username to $MailboxType mailbox. Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - return "Could not convert $username to a $MailboxType mailbox. Error: $($ErrorMessage.NormalizedError)" + $Message = "Could not convert $Username to a $MailboxType mailbox. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + return $Message } } From cb477ee1d431b3531a084dd50b6eac47d498e2c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 17 Feb 2025 18:29:45 +0100 Subject: [PATCH 011/167] Change to POST --- .../CIPPCore/Public/Invoke-RemoveContact.ps1 | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/Modules/CIPPCore/Public/Invoke-RemoveContact.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveContact.ps1 index 1494650832e9..573cca5550d2 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveContact.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveContact.ps1 @@ -11,30 +11,32 @@ Function Invoke-RemoveContact { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $Tenantfilter = $request.Query.tenantfilter - $User = $Request.Headers - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $TenantFilter = $Request.Query.tenantFilter + Write-LogMessage -Headers $Request.Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - - $Params = @{ - Identity = $request.query.guid - } + # Interact with query parameters or the body of the request. + $GUID = $Request.query.GUID ?? $Request.body.GUID try { - $Params = @{ Identity = $request.query.GUID } - - $null = New-ExoRequest -tenantid $Tenantfilter -cmdlet 'Remove-MailContact' -cmdParams $params -UseSystemMailbox $true - $Result = "Deleted $($Request.query.guid)" - Write-LogMessage -Headers $User -API $APIName -tenant $tenantfilter -message "Deleted contact $($Request.query.guid)" -sev Debug + $Params = @{ + Identity = $GUID + } + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Remove-MailContact' -cmdParams $Params -UseSystemMailbox $true + Write-LogMessage -Headers $Request.Headers -API $APIName -tenant $TenantFilter -message "Deleted contact $GUID" -sev Debug + $Result = "Deleted $GUID" + $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APIName -tenant $tenantfilter -message "Failed to delete contact $($Request.query.guid). $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage - $Result = $ErrorMessage.NormalizedError + $Result = "Failed to delete contact $GUID. $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Request.Headers -API $APIName -tenant $TenantFilter -message $Result -sev Error -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::BadRequest } + + $Results = [pscustomobject]@{'Results' = $Result } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = @{Results = $Result } + StatusCode = $StatusCode + Body = $Results }) } From fa94d4b2e0da626f4978c1cf20729083f1428f2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 17 Feb 2025 18:47:24 +0100 Subject: [PATCH 012/167] Implement and replace mailbox conversions with Invoke-ExecConvertMailbox statuscode and remove useless stuff Refactor Invoke-RemoveAPDevice to unify tenant filter retrieval and improve logging messages --- ...lbox.ps1 => Invoke-ExecConvertMailbox.ps1} | 12 ++-- .../Invoke-ExecConverttoSharedMailbox.ps1 | 39 ----------- .../Entrypoints/Invoke-ListFunctionStats.ps1 | 10 +-- .../Entrypoints/Invoke-ListRoomLists.ps1 | 8 +-- .../Public/Invoke-CIPPOffboardingJob.ps1 | 64 +++++++++---------- .../CIPPCore/Public/Invoke-RemoveAPDevice.ps1 | 21 +++--- .../CIPPCore/Public/Invoke-RemovePolicy.ps1 | 6 +- 7 files changed, 57 insertions(+), 103 deletions(-) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{Invoke-ExecConverttoRoomMailbox.ps1 => Invoke-ExecConvertMailbox.ps1} (77%) delete mode 100644 Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConverttoSharedMailbox.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConverttoRoomMailbox.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConvertMailbox.ps1 similarity index 77% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConverttoRoomMailbox.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConvertMailbox.ps1 index e67d20942705..b8bd40c0915a 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConverttoRoomMailbox.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConvertMailbox.ps1 @@ -1,6 +1,6 @@ using namespace System.Net -Function Invoke-ExecConvertToRoomMailbox { +Function Invoke-ExecConvertMailbox { <# .FUNCTIONALITY Entrypoint @@ -11,20 +11,20 @@ Function Invoke-ExecConvertToRoomMailbox { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $TenantFilter = $Request.Body.tenantFilter Write-LogMessage -Headers $Request.Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' # Interact with query parameters or the body of the request. - $UserID = $Request.Query.ID ?? $Request.Body.ID + $UserID = $Request.Body.ID + $MailboxType = $Request.Body.MailboxType - Try { - $ConvertedMailbox = Set-CIPPMailboxType -UserID $UserID -TenantFilter $TenantFilter -APIName $APIName -Headers $Request.Headers -MailboxType 'Room' + try { + $ConvertedMailbox = Set-CIPPMailboxType -UserID $UserID -TenantFilter $TenantFilter -APIName $APIName -Headers $Request.Headers -MailboxType $MailboxType if ($ConvertedMailbox -like 'Could not convert*') { throw $ConvertedMailbox } $Results = [pscustomobject]@{'Results' = "$ConvertedMailbox" } $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = $_.Exception.Message - Write-LogMessage -Headers $Request.Headers -API $APIName -message "Error converting mailbox: $ErrorMessage" -Sev 'Error' $Results = [pscustomobject]@{'Results' = "$ErrorMessage" } $StatusCode = [HttpStatusCode]::InternalServerError } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConverttoSharedMailbox.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConverttoSharedMailbox.ps1 deleted file mode 100644 index b704bac3dd5b..000000000000 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConverttoSharedMailbox.ps1 +++ /dev/null @@ -1,39 +0,0 @@ -using namespace System.Net - -Function Invoke-ExecConverttoSharedMailbox { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.Mailbox.ReadWrite - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - $Tenant = $Request.query.TenantFilter - $User = $Request.Headers - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - - - # Interact with query parameters or the body of the request. - Try { - $MailboxType = if ($request.query.ConvertToUser -eq 'true') { 'Regular' } else { 'Shared' } - $ConvertedMailbox = Set-CIPPMailboxType -userid $Request.query.id -tenantFilter $Tenant -APIName $APINAME -Headers $User -MailboxType $MailboxType - $Results = [pscustomobject]@{'Results' = "$ConvertedMailbox" } - $StatusCode = [HttpStatusCode]::OK - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - $Results = [pscustomobject]@{'Results' = "Failed to convert $($request.query.id) - $ErrorMessage" } - $StatusCode = [HttpStatusCode]::Forbidden - } - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $StatusCode - Body = $Results - }) - -} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionStats.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionStats.ps1 index 26c014d0c8d5..257d6c32e6cb 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionStats.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionStats.ps1 @@ -13,10 +13,6 @@ Function Invoke-ListFunctionStats { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - # Interact with query parameters or the body of the request. - try { $TenantFilter = $Request.Query.TenantFilter $PartitionKey = $Request.Query.FunctionType @@ -69,7 +65,7 @@ Function Invoke-ListFunctionStats { 'AvgSeconds' = $Stats.Average } } - $Status = [HttpStatusCode]::OK + $StatusCode = [HttpStatusCode]::OK $Body = @{ Results = @{ Functions = @($FunctionStats) @@ -80,7 +76,7 @@ Function Invoke-ListFunctionStats { } } } catch { - $Status = [HttpStatusCode]::BadRequest + $StatusCode = [HttpStatusCode]::BadRequest $Body = @{ Results = @() Metadata = @{ @@ -91,7 +87,7 @@ Function Invoke-ListFunctionStats { } Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $Status + StatusCode = $StatusCode Body = $Body }) -Clobber diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRoomLists.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRoomLists.ps1 index 93ac7fb9041c..bf4891463fa7 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRoomLists.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRoomLists.ps1 @@ -11,14 +11,10 @@ Function Invoke-ListRoomLists { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + Write-LogMessage -headers $Request.Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' # Interact with query parameters or the body of the request. - $TenantFilter = $Request.Query.TenantFilter + $TenantFilter = $Request.Query.tenantFilter try { $params = @{ diff --git a/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 b/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 index 02d2d21114ea..c39c7879be09 100644 --- a/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 +++ b/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 @@ -12,64 +12,64 @@ function Invoke-CIPPOffboardingJob { if ($Options -is [string]) { $Options = $Options | ConvertFrom-Json } - $userid = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($username)?`$select=id" -tenantid $Tenantfilter).id + $userid = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($username)?`$select=id" -tenantid $TenantFilter).id Write-Host "Running offboarding job for $username with options: $($Options | ConvertTo-Json -Depth 10)" $Return = switch ($Options) { - { $_.'ConvertToShared' -eq $true } { - Set-CIPPMailboxType -Headers $Headers -tenantFilter $tenantFilter -userid $username -username $username -MailboxType 'Shared' -APIName $APIName + { $_.ConvertToShared -eq $true } { + Set-CIPPMailboxType -Headers $Headers -tenantFilter $TenantFilter -userid $username -username $username -MailboxType 'Shared' -APIName $APIName } { $_.RevokeSessions -eq $true } { - Revoke-CIPPSessions -tenantFilter $tenantFilter -username $username -userid $userid -Headers $Headers -APIName $APIName + Revoke-CIPPSessions -tenantFilter $TenantFilter -username $username -userid $userid -Headers $Headers -APIName $APIName } { $_.ResetPass -eq $true } { - Set-CIPPResetPassword -tenantFilter $tenantFilter -UserID $username -Headers $Headers -APIName $APIName + Set-CIPPResetPassword -tenantFilter $TenantFilter -UserID $username -Headers $Headers -APIName $APIName } { $_.RemoveGroups -eq $true } { - Remove-CIPPGroups -userid $userid -tenantFilter $Tenantfilter -Headers $Headers -APIName $APIName -Username "$Username" + Remove-CIPPGroups -userid $userid -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName -Username "$Username" } - { $_.'HideFromGAL' -eq $true } { - Set-CIPPHideFromGAL -tenantFilter $tenantFilter -UserID $username -hidefromgal $true -Headers $Headers -APIName $APIName + { $_.HideFromGAL -eq $true } { + Set-CIPPHideFromGAL -tenantFilter $TenantFilter -UserID $username -hidefromgal $true -Headers $Headers -APIName $APIName } - { $_.'DisableSignIn' -eq $true } { - Set-CIPPSignInState -TenantFilter $tenantFilter -userid $username -AccountEnabled $false -Headers $Headers -APIName $APIName + { $_.DisableSignIn -eq $true } { + Set-CIPPSignInState -TenantFilter $TenantFilter -userid $username -AccountEnabled $false -Headers $Headers -APIName $APIName } - { $_.'OnedriveAccess' } { - $Options.OnedriveAccess | ForEach-Object { Set-CIPPSharePointPerms -tenantFilter $tenantFilter -userid $username -OnedriveAccessUser $_.value -Headers $Headers -APIName $APIName } + { $_.OnedriveAccess } { + $Options.OnedriveAccess | ForEach-Object { Set-CIPPSharePointPerms -tenantFilter $TenantFilter -userid $username -OnedriveAccessUser $_.value -Headers $Headers -APIName $APIName } } - { $_.'AccessNoAutomap' } { - $Options.AccessNoAutomap | ForEach-Object { Set-CIPPMailboxAccess -tenantFilter $tenantFilter -userid $username -AccessUser $_.value -Automap $false -AccessRights @('FullAccess') -Headers $Headers -APIName $APIName } + { $_.AccessNoAutomap } { + $Options.AccessNoAutomap | ForEach-Object { Set-CIPPMailboxAccess -tenantFilter $TenantFilter -userid $username -AccessUser $_.value -Automap $false -AccessRights @('FullAccess') -Headers $Headers -APIName $APIName } } - { $_.'AccessAutomap' } { - $Options.AccessAutomap | ForEach-Object { Set-CIPPMailboxAccess -tenantFilter $tenantFilter -userid $username -AccessUser $_.value -Automap $true -AccessRights @('FullAccess') -Headers $Headers -APIName $APIName } + { $_.AccessAutomap } { + $Options.AccessAutomap | ForEach-Object { Set-CIPPMailboxAccess -tenantFilter $TenantFilter -userid $username -AccessUser $_.value -Automap $true -AccessRights @('FullAccess') -Headers $Headers -APIName $APIName } } - { $_.'OOO' } { - Set-CIPPOutOfOffice -tenantFilter $tenantFilter -userid $username -InternalMessage $Options.OOO -ExternalMessage $Options.OOO -Headers $Headers -APIName $APIName -state 'Enabled' + { $_.OOO } { + Set-CIPPOutOfOffice -tenantFilter $TenantFilter -userid $username -InternalMessage $Options.OOO -ExternalMessage $Options.OOO -Headers $Headers -APIName $APIName -state 'Enabled' } - { $_.'forward' } { + { $_.forward } { if (!$Options.keepCopy) { - Set-CIPPForwarding -userid $userid -username $username -tenantFilter $Tenantfilter -Forward $Options.forward.value -Headers $Headers -APIName $APIName + Set-CIPPForwarding -userid $userid -username $username -tenantFilter $TenantFilter -Forward $Options.forward.value -Headers $Headers -APIName $APIName } else { $KeepCopy = [boolean]$Options.keepCopy - Set-CIPPForwarding -userid $userid -username $username -tenantFilter $Tenantfilter -Forward $Options.forward.value -KeepCopy $KeepCopy -Headers $Headers -APIName $APIName + Set-CIPPForwarding -userid $userid -username $username -tenantFilter $TenantFilter -Forward $Options.forward.value -KeepCopy $KeepCopy -Headers $Headers -APIName $APIName } } - { $_.'RemoveLicenses' -eq $true } { - Remove-CIPPLicense -userid $userid -username $Username -tenantFilter $Tenantfilter -Headers $Headers -APIName $APIName -Schedule + { $_.RemoveLicenses -eq $true } { + Remove-CIPPLicense -userid $userid -username $Username -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName -Schedule } - { $_.'deleteuser' -eq $true } { - Remove-CIPPUser -userid $userid -username $Username -tenantFilter $Tenantfilter -Headers $Headers -APIName $APIName + { $_.deleteuser -eq $true } { + Remove-CIPPUser -userid $userid -username $Username -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName } - { $_.'removeRules' -eq $true } { + { $_.removeRules -eq $true } { Write-Host "Removing rules for $username" - Remove-CIPPMailboxRule -userid $userid -username $Username -tenantFilter $Tenantfilter -Headers $Headers -APIName $APIName -RemoveAllRules + Remove-CIPPMailboxRule -userid $userid -username $Username -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName -RemoveAllRules } - { $_.'removeMobile' -eq $true } { - Remove-CIPPMobileDevice -userid $userid -username $Username -tenantFilter $Tenantfilter -Headers $Headers -APIName $APIName + { $_.removeMobile -eq $true } { + Remove-CIPPMobileDevice -userid $userid -username $Username -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName } - { $_.'removeCalendarInvites' -eq $true } { - Remove-CIPPCalendarInvites -userid $userid -username $Username -tenantFilter $Tenantfilter -Headers $Headers -APIName $APIName + { $_.removeCalendarInvites -eq $true } { + Remove-CIPPCalendarInvites -userid $userid -username $Username -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName } - { $_.'removePermissions' } { + { $_.removePermissions } { if ($RunScheduled) { Remove-CIPPMailboxPermissions -PermissionsLevel @('FullAccess', 'SendAs', 'SendOnBehalf') -userid 'AllUsers' -AccessUser $UserName -TenantFilter $TenantFilter -APIName $APINAME -Headers $Headers diff --git a/Modules/CIPPCore/Public/Invoke-RemoveAPDevice.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveAPDevice.ps1 index c04a4c40b4ed..839a5410bb22 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveAPDevice.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveAPDevice.ps1 @@ -12,12 +12,10 @@ Function Invoke-RemoveAPDevice { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' # Interact with query parameters or the body of the request. - $TenantFilter = $Request.Query.TenantFilter - $Deviceid = $Request.Query.ID + $TenantFilter = $Request.Query.tenantFilter ?? $Request.body.tenantFilter + $Deviceid = $Request.Query.ID ?? $Request.body.ID try { if ($null -eq $TenantFilter -or $TenantFilter -eq 'null') { @@ -25,19 +23,22 @@ Function Invoke-RemoveAPDevice { } else { $null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeviceIdentities/$Deviceid" -tenantid $TenantFilter -type DELETE } - Write-LogMessage -headers $Request.Headers -tenant $TenantFilter -API $APINAME -message "Deleted autopilot device $Deviceid" -Sev 'Info' - $body = [pscustomobject]@{'Results' = 'Successfully deleted the autopilot device' } + $Result = "Deleted autopilot device $Deviceid" + Write-LogMessage -headers $Request.Headers -tenant $TenantFilter -API $APIName -message $Result -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Request.Headers -tenant $TenantFilter -API $APINAME -message "Autopilot Delete API failed for $deviceid. The error is: $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage - $body = [pscustomobject]@{'Results' = "Failed to delete device: $($ErrorMessage.NormalizedError)" } + $Result = "Failed to delete device $($Deviceid): $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Request.Headers -tenant $TenantFilter -API $APIName -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } - #force a sync, this can give "too many requests" if deleleting a bunch of devices though. + # Force a sync, this can give "too many requests" if deleting a bunch of devices though. $null = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotSettings/sync' -tenantid $TenantFilter -type POST -body '{}' + $Body = [pscustomobject]@{'Results' = "$Result" } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK + StatusCode = $StatusCode Body = $Body }) diff --git a/Modules/CIPPCore/Public/Invoke-RemovePolicy.ps1 b/Modules/CIPPCore/Public/Invoke-RemovePolicy.ps1 index 2720fda34755..af0206cc0619 100644 --- a/Modules/CIPPCore/Public/Invoke-RemovePolicy.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemovePolicy.ps1 @@ -22,7 +22,7 @@ Function Invoke-RemovePolicy { if (!$PolicyId) { exit } try { - #$unAssignRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($PolicyId)')/assign" -type POST -Body '{"assignments":[]}' -tenant $TenantFilter + # $unAssignRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($PolicyId)')/assign" -type POST -Body '{"assignments":[]}' -tenant $TenantFilter $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($UrlName)('$($PolicyId)')" -type DELETE -tenant $TenantFilter $Results = "Successfully deleted the policy with ID: $($PolicyId)" Write-LogMessage -headers $Headers -API $APINAME -message $Results -Sev Info -tenant $TenantFilter @@ -35,11 +35,11 @@ Function Invoke-RemovePolicy { $StatusCode = [HttpStatusCode]::Forbidden } - $body = [pscustomobject]@{'Results' = "$Results" } + $Body = [pscustomobject]@{'Results' = "$Results" } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = $StatusCode - Body = $body + Body = $Body }) From e3ca0a03fa68d6e09f9764793fc9658b0ada325e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 17 Feb 2025 20:20:42 +0100 Subject: [PATCH 013/167] Support POST and new messages --- Modules/CIPPCore/Public/Invoke-RemoveApp.ps1 | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Modules/CIPPCore/Public/Invoke-RemoveApp.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveApp.ps1 index b38057ad16ee..a58aa9f73140 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveApp.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveApp.ps1 @@ -15,25 +15,26 @@ Function Invoke-RemoveApp { Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' # Interact with query parameters or the body of the request. - $TenantFilter = $Request.Query.TenantFilter - $policyId = $Request.Query.ID + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $policyId = $Request.Query.ID ?? $Request.Body.ID if (!$policyId) { exit } try { #$unAssignRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($policyId)')/assign" -type POST -Body '{"assignments":[]}' -tenant $TenantFilter $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/$($policyId)" -type DELETE -tenant $TenantFilter - Write-LogMessage -Headers $User -API $APINAME -message "Deleted $policyId" -Sev 'Info' -tenant $TenantFilter - $body = [pscustomobject]@{'Results' = 'Successfully deleted the application' } + $Result = "Successfully deleted app with $policyId" + Write-LogMessage -Headers $User -API $APINAME -message $Result -Sev 'Info' -tenant $TenantFilter } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -message "Could not delete app $policyId. $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - $body = [pscustomobject]@{'Results' = "Could not delete this application: $($ErrorMessage.NormalizedError)" } + $Result = "Could not delete app with $policyId. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $User -API $APINAME -message $Result -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage } + $Body = [pscustomobject]@{Results = "$Result" } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK - Body = $body + Body = $Body }) From 23923ad213c41f2e740cd50c4d0ec8b52684185f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 17 Feb 2025 20:28:22 +0100 Subject: [PATCH 014/167] Change to POST and modernize --- .../Entrypoints/Invoke-ExecRestoreDeleted.ps1 | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecRestoreDeleted.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecRestoreDeleted.ps1 index 3547e651798d..e2d85fae5706 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecRestoreDeleted.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecRestoreDeleted.ps1 @@ -14,18 +14,25 @@ Function Invoke-ExecRestoreDeleted { Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' # Interact with query parameters or the body of the request. - $TenantFilter = $Request.Query.TenantFilter + $TenantFilter = $Request.Query.TenantFilter ?? $Request.Body.TenantFilter + $RequestID = $Request.Query.ID ?? $Request.Body.ID try { - $GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/v1.0/directory/deletedItems/$($Request.query.ID)/restore" -tenantid $TenantFilter -type POST -body '{}' -verbose - $Results = [pscustomobject]@{'Results' = 'Successfully completed request.' } + $null = New-GraphPostRequest -uri "https://graph.microsoft.com/v1.0/directory/deletedItems/$($RequestID)/restore" -tenantid $TenantFilter -type POST -body '{}' -Verbose + $Result = "Successfully restored deleted item with ID: $($RequestID)" + Write-LogMessage -headers $Request.Headers -tenant $TenantFilter -API $APIName -message $Result -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK } catch { - $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" } + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed to restore deleted item with ID: $($RequestID). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Request.Headers -tenant $TenantFilter -API $APIName -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } + $Results = [pscustomobject]@{'Results' = $Result } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK + StatusCode = $StatusCode Body = $Results }) From 70a6683a0ed431cfe82fb6bff470771916ad1b9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 17 Feb 2025 20:39:07 +0100 Subject: [PATCH 015/167] Fix casing for tenant filter and improve error logging in Invoke-ListSharedMailboxAccountEnabled --- .../Invoke-ListSharedMailboxAccountEnabled.ps1 | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxAccountEnabled.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxAccountEnabled.ps1 index c7d6d401ab1f..1740ad53cc8d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxAccountEnabled.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxAccountEnabled.ps1 @@ -14,15 +14,12 @@ Function Invoke-ListSharedMailboxAccountEnabled { Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - - $TenantFilter = $Request.Query.TenantFilter + $TenantFilter = $Request.Query.tenantFilter # Get Shared Mailbox Stuff try { $SharedMailboxList = (New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($TenantFilter)/Mailbox?`$filter=RecipientTypeDetails eq 'SharedMailbox'" -Tenantid $TenantFilter -scope ExchangeOnline) - $AllUsersAccountState = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/users?select=id,userPrincipalName,accountEnabled,displayName,givenName,surname,onPremisesSyncEnabled' -tenantid $Tenantfilter + $AllUsersAccountState = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/users?select=id,userPrincipalName,accountEnabled,displayName,givenName,surname,onPremisesSyncEnabled' -tenantid $TenantFilter $EnabledUsersWithSharedMailbox = foreach ($SharedMailbox in $SharedMailboxList) { # Match the User $User = $AllUsersAccountState | Where-Object { $_.userPrincipalName -eq $SharedMailbox.userPrincipalName } | Select-Object -Property id, userPrincipalName, accountEnabled, displayName, givenName, surname, onPremisesSyncEnabled -First 1 @@ -38,9 +35,8 @@ Function Invoke-ListSharedMailboxAccountEnabled { } } - } - catch { - Write-LogMessage -API 'Tenant' -tenant $tenantfilter -message "Shared Mailbox Enabled Accounts on $($tenantfilter). Error: $($_.exception.message)" -sev 'Error' + } catch { + Write-LogMessage -API 'Tenant' -tenant $TenantFilter -message "Shared Mailbox Enabled Accounts on $($TenantFilter). Error: $($_.exception.message)" -sev 'Error' } $GraphRequest = $EnabledUsersWithSharedMailbox From 0a61a459127c49280c2958505e4965e5389d52dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 17 Feb 2025 20:45:30 +0100 Subject: [PATCH 016/167] Fix casing for Get-UnifiedGroup command and improve logging in Invoke-ListGroupSenderAuthentication --- .../Groups/Invoke-ListGroupSenderAuthentication.ps1 | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroupSenderAuthentication.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroupSenderAuthentication.ps1 index 11d70a0f2f8a..70672eb22229 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroupSenderAuthentication.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroupSenderAuthentication.ps1 @@ -6,11 +6,8 @@ Function Invoke-ListGroupSenderAuthentication { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' # Interact with query parameters or the body of the request. - $TenantFilter = $Request.Query.TenantFilter $groupid = $Request.query.groupid $GroupType = $Request.query.Type @@ -28,7 +25,7 @@ Function Invoke-ListGroupSenderAuthentication { } 'Microsoft 365' { Write-Host 'Checking M365 Group' - $State = (New-ExoRequest -tenantid $TenantFilter -cmdlet 'get-unifiedgroup' -cmdParams $params -UseSystemMailbox $true).RequireSenderAuthenticationEnabled + $State = (New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-UnifiedGroup' -cmdParams $params -UseSystemMailbox $true).RequireSenderAuthenticationEnabled } default { $state = $true } From 941b6be225fef422fedb70e551bfe808b3e73b9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 17 Feb 2025 21:02:05 +0100 Subject: [PATCH 017/167] Move some endpoints around --- .../Invoke-AddTenantAllowBlockList.ps1 | 0 .../Invoke-ListCalendarPermissions.ps1 | 0 .../Email-Exchange}/Invoke-ListContacts.ps1 | 0 .../Invoke-ListExchangeConnectors.ps1 | 0 .../Email-Exchange}/Invoke-ListMailboxes.ps1 | 0 .../Email-Exchange}/Invoke-ListRoomLists.ps1 | 0 .../Email-Exchange}/Invoke-ListRooms.ps1 | 0 .../Invoke-ListAntiPhishingFilters.ps1 | 66 +++++++++---------- .../Invoke-ListGlobalAddressList.ps1 | 0 .../Reports}/Invoke-ListMailboxCAS.ps1 | 0 .../Invoke-ListMalwareFilters.ps1 | 66 +++++++++---------- .../Invoke-ListSafeAttachmentsFilters.ps1 | 66 +++++++++---------- .../Invoke-ListSafeLinksFilters.ps1 | 66 +++++++++---------- ...Invoke-ListSharedMailboxAccountEnabled.ps1 | 0 .../Applications}/Invoke-RemoveApp.ps1 | 0 .../Autopilot}/Invoke-ExecSyncAPDevices.ps1 | 0 .../Autopilot}/Invoke-ListAutopilotconfig.ps1 | 0 .../Autopilot}/Invoke-RemoveAPDevice.ps1 | 0 .../Groups}/Invoke-ListGroups.ps1 | 0 .../Users}/Invoke-ExecRestoreDeleted.ps1 | 0 .../Users}/Invoke-ListDeletedItems.ps1 | 0 .../Invoke-ListAzureADConnectStatus.ps1 | 0 .../Reports}/Invoke-ListInactiveAccounts.ps1 | 0 .../Identity/Reports}/Invoke-ListMFAUsers.ps1 | 0 .../Identity/Reports}/Invoke-ListSignIns.ps1 | 0 .../Tenant/Reports}/Invoke-ListLicenses.ps1 | 0 .../Tenant/Reports}/Invoke-ListOAuthApps.ps1 | 0 27 files changed, 132 insertions(+), 132 deletions(-) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Email-Exchange}/Invoke-AddTenantAllowBlockList.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Email-Exchange}/Invoke-ListCalendarPermissions.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Email-Exchange}/Invoke-ListContacts.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Email-Exchange}/Invoke-ListExchangeConnectors.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Email-Exchange}/Invoke-ListMailboxes.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Email-Exchange}/Invoke-ListRoomLists.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Email-Exchange}/Invoke-ListRooms.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Reports}/Invoke-ListAntiPhishingFilters.ps1 (98%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Reports}/Invoke-ListGlobalAddressList.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Email-Exchange/Reports}/Invoke-ListMailboxCAS.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Reports}/Invoke-ListMalwareFilters.ps1 (98%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Reports}/Invoke-ListSafeAttachmentsFilters.ps1 (98%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Reports}/Invoke-ListSafeLinksFilters.ps1 (98%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Email-Exchange/Reports}/Invoke-ListSharedMailboxAccountEnabled.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Endpoint/Applications}/Invoke-RemoveApp.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Endpoint/Autopilot}/Invoke-ExecSyncAPDevices.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Endpoint/Autopilot}/Invoke-ListAutopilotconfig.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Endpoint/Autopilot}/Invoke-RemoveAPDevice.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Identity/Administration/Groups}/Invoke-ListGroups.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Identity/Administration/Users}/Invoke-ExecRestoreDeleted.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Identity/Administration/Users}/Invoke-ListDeletedItems.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Identity/Reports}/Invoke-ListAzureADConnectStatus.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Identity/Reports}/Invoke-ListInactiveAccounts.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Identity/Reports}/Invoke-ListMFAUsers.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Identity/Reports}/Invoke-ListSignIns.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Tenant/Reports}/Invoke-ListLicenses.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Tenant/Reports}/Invoke-ListOAuthApps.ps1 (100%) diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-AddTenantAllowBlockList.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddTenantAllowBlockList.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-AddTenantAllowBlockList.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddTenantAllowBlockList.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCalendarPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListCalendarPermissions.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListCalendarPermissions.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListCalendarPermissions.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListContacts.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListContacts.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListContacts.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListContacts.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExchangeConnectors.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListExchangeConnectors.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListExchangeConnectors.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListExchangeConnectors.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxes.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMailboxes.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxes.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMailboxes.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRoomLists.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListRoomLists.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListRoomLists.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListRoomLists.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRooms.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListRooms.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListRooms.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListRooms.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListAntiPhishingFilters.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListAntiPhishingFilters.ps1 similarity index 98% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListAntiPhishingFilters.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListAntiPhishingFilters.ps1 index d6075e578313..2f2d87e830b9 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListAntiPhishingFilters.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListAntiPhishingFilters.ps1 @@ -1,33 +1,33 @@ -function Invoke-ListAntiPhishingFilters { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.SpamFilter.Read - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - - # Interact with query parameters or the body of the request. - $TenantFilter = $Request.Query.TenantFilter - $Policys = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-AntiPhishPolicy' | Select-Object -Property * - $Rules = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-AntiPhishRule' | Select-Object -Property * - - $Output = $Policys | Select-Object -Property *, - @{ Name = 'RuleName'; Expression = { foreach ($item in $Rules) { if ($item.AntiPhishPolicy -eq $_.Name) { $item.Name } } } }, - @{ Name = 'Priority'; Expression = { foreach ($item in $Rules) { if ($item.AntiPhishPolicy -eq $_.Name) { $item.Priority } } } }, - @{ Name = 'RecipientDomainIs'; Expression = { foreach ($item in $Rules) { if ($item.AntiPhishPolicy -eq $_.Name) { $item.RecipientDomainIs } } } }, - @{ Name = 'State'; Expression = { foreach ($item in $Rules) { if ($item.AntiPhishPolicy -eq $_.Name) { $item.State } } } } - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Output - }) -} +function Invoke-ListAntiPhishingFilters { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.SpamFilter.Read + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + + # Write to the Azure Functions log stream. + Write-Host 'PowerShell HTTP trigger function processed a request.' + + # Interact with query parameters or the body of the request. + $TenantFilter = $Request.Query.TenantFilter + $Policys = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-AntiPhishPolicy' | Select-Object -Property * + $Rules = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-AntiPhishRule' | Select-Object -Property * + + $Output = $Policys | Select-Object -Property *, + @{ Name = 'RuleName'; Expression = { foreach ($item in $Rules) { if ($item.AntiPhishPolicy -eq $_.Name) { $item.Name } } } }, + @{ Name = 'Priority'; Expression = { foreach ($item in $Rules) { if ($item.AntiPhishPolicy -eq $_.Name) { $item.Priority } } } }, + @{ Name = 'RecipientDomainIs'; Expression = { foreach ($item in $Rules) { if ($item.AntiPhishPolicy -eq $_.Name) { $item.RecipientDomainIs } } } }, + @{ Name = 'State'; Expression = { foreach ($item in $Rules) { if ($item.AntiPhishPolicy -eq $_.Name) { $item.State } } } } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $Output + }) +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListGlobalAddressList.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListGlobalAddressList.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListGlobalAddressList.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListGlobalAddressList.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxCAS.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMailboxCAS.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxCAS.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMailboxCAS.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMalwareFilters.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMalwareFilters.ps1 similarity index 98% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMalwareFilters.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMalwareFilters.ps1 index 597472165fda..ae91d9091d1d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMalwareFilters.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMalwareFilters.ps1 @@ -1,33 +1,33 @@ -function Invoke-ListMalwareFilters { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.SpamFilter.Read - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - - # Interact with query parameters or the body of the request. - $TenantFilter = $Request.Query.TenantFilter - $Policys = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-MalwareFilterPolicy' | Select-Object -Property * - $Rules = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-MalwareFilterRule' | Select-Object -Property * - - $Output = $Policys | Select-Object -Property *, - @{ Name = 'RuleName'; Expression = { foreach ($item in $Rules) { if ($item.MalwareFilterPolicy -eq $_.Name) { $item.Name } } } }, - @{ Name = 'Priority'; Expression = { foreach ($item in $Rules) { if ($item.MalwareFilterPolicy -eq $_.Name) { $item.Priority } } } }, - @{ Name = 'RecipientDomainIs'; Expression = { foreach ($item in $Rules) { if ($item.MalwareFilterPolicy -eq $_.Name) { $item.RecipientDomainIs } } } }, - @{ Name = 'State'; Expression = { foreach ($item in $Rules) { if ($item.MalwareFilterPolicy -eq $_.Name) { $item.State } } } } - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Output - }) -} +function Invoke-ListMalwareFilters { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.SpamFilter.Read + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + + # Write to the Azure Functions log stream. + Write-Host 'PowerShell HTTP trigger function processed a request.' + + # Interact with query parameters or the body of the request. + $TenantFilter = $Request.Query.TenantFilter + $Policys = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-MalwareFilterPolicy' | Select-Object -Property * + $Rules = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-MalwareFilterRule' | Select-Object -Property * + + $Output = $Policys | Select-Object -Property *, + @{ Name = 'RuleName'; Expression = { foreach ($item in $Rules) { if ($item.MalwareFilterPolicy -eq $_.Name) { $item.Name } } } }, + @{ Name = 'Priority'; Expression = { foreach ($item in $Rules) { if ($item.MalwareFilterPolicy -eq $_.Name) { $item.Priority } } } }, + @{ Name = 'RecipientDomainIs'; Expression = { foreach ($item in $Rules) { if ($item.MalwareFilterPolicy -eq $_.Name) { $item.RecipientDomainIs } } } }, + @{ Name = 'State'; Expression = { foreach ($item in $Rules) { if ($item.MalwareFilterPolicy -eq $_.Name) { $item.State } } } } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $Output + }) +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListSafeAttachmentsFilters.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeAttachmentsFilters.ps1 similarity index 98% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListSafeAttachmentsFilters.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeAttachmentsFilters.ps1 index 8b71d807876f..1138b77c2642 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListSafeAttachmentsFilters.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeAttachmentsFilters.ps1 @@ -1,33 +1,33 @@ -function Invoke-ListSafeAttachmentsFilters { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.SpamFilter.Read - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - - # Interact with query parameters or the body of the request. - $TenantFilter = $Request.Query.TenantFilter - $Policys = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-SafeAttachmentPolicy' | Select-Object -Property * - $Rules = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-SafeAttachmentRule' | Select-Object -Property * - - $Output = $Policys | Select-Object -Property *, - @{ Name = 'RuleName'; Expression = { foreach ($item in $Rules) { if ($item.SafeAttachmentPolicy -eq $_.Name) { $item.Name } } } }, - @{ Name = 'Priority'; Expression = { foreach ($item in $Rules) { if ($item.SafeAttachmentPolicy -eq $_.Name) { $item.Priority } } } }, - @{ Name = 'RecipientDomainIs'; Expression = { foreach ($item in $Rules) { if ($item.SafeAttachmentPolicy -eq $_.Name) { $item.RecipientDomainIs } } } }, - @{ Name = 'State'; Expression = { foreach ($item in $Rules) { if ($item.SafeAttachmentPolicy -eq $_.Name) { $item.State } } } } - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Output - }) -} +function Invoke-ListSafeAttachmentsFilters { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.SpamFilter.Read + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + + # Write to the Azure Functions log stream. + Write-Host 'PowerShell HTTP trigger function processed a request.' + + # Interact with query parameters or the body of the request. + $TenantFilter = $Request.Query.TenantFilter + $Policys = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-SafeAttachmentPolicy' | Select-Object -Property * + $Rules = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-SafeAttachmentRule' | Select-Object -Property * + + $Output = $Policys | Select-Object -Property *, + @{ Name = 'RuleName'; Expression = { foreach ($item in $Rules) { if ($item.SafeAttachmentPolicy -eq $_.Name) { $item.Name } } } }, + @{ Name = 'Priority'; Expression = { foreach ($item in $Rules) { if ($item.SafeAttachmentPolicy -eq $_.Name) { $item.Priority } } } }, + @{ Name = 'RecipientDomainIs'; Expression = { foreach ($item in $Rules) { if ($item.SafeAttachmentPolicy -eq $_.Name) { $item.RecipientDomainIs } } } }, + @{ Name = 'State'; Expression = { foreach ($item in $Rules) { if ($item.SafeAttachmentPolicy -eq $_.Name) { $item.State } } } } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $Output + }) +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListSafeLinksFilters.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeLinksFilters.ps1 similarity index 98% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListSafeLinksFilters.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeLinksFilters.ps1 index bcf5e939e498..0b4c2d60788b 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListSafeLinksFilters.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeLinksFilters.ps1 @@ -1,33 +1,33 @@ -function Invoke-ListSafeLinksFilters { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.SpamFilter.Read - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - - # Interact with query parameters or the body of the request. - $TenantFilter = $Request.Query.TenantFilter - $Policys = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-SafeLinksPolicy' | Select-Object -Property * - $Rules = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-SafeLinksRule' | Select-Object -Property * - - $Output = $Policys | Select-Object -Property *, - @{ Name = 'RuleName'; Expression = { foreach ($item in $Rules) { if ($item.SafeLinksPolicy -eq $_.Name) { $item.Name } } } }, - @{ Name = 'Priority'; Expression = { foreach ($item in $Rules) { if ($item.SafeLinksPolicy -eq $_.Name) { $item.Priority } } } }, - @{ Name = 'RecipientDomainIs'; Expression = { foreach ($item in $Rules) { if ($item.SafeLinksPolicy -eq $_.Name) { $item.RecipientDomainIs } } } }, - @{ Name = 'State'; Expression = { foreach ($item in $Rules) { if ($item.SafeLinksPolicy -eq $_.Name) { $item.State } } } } - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Output - }) -} +function Invoke-ListSafeLinksFilters { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.SpamFilter.Read + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + + # Write to the Azure Functions log stream. + Write-Host 'PowerShell HTTP trigger function processed a request.' + + # Interact with query parameters or the body of the request. + $TenantFilter = $Request.Query.TenantFilter + $Policys = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-SafeLinksPolicy' | Select-Object -Property * + $Rules = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-SafeLinksRule' | Select-Object -Property * + + $Output = $Policys | Select-Object -Property *, + @{ Name = 'RuleName'; Expression = { foreach ($item in $Rules) { if ($item.SafeLinksPolicy -eq $_.Name) { $item.Name } } } }, + @{ Name = 'Priority'; Expression = { foreach ($item in $Rules) { if ($item.SafeLinksPolicy -eq $_.Name) { $item.Priority } } } }, + @{ Name = 'RecipientDomainIs'; Expression = { foreach ($item in $Rules) { if ($item.SafeLinksPolicy -eq $_.Name) { $item.RecipientDomainIs } } } }, + @{ Name = 'State'; Expression = { foreach ($item in $Rules) { if ($item.SafeLinksPolicy -eq $_.Name) { $item.State } } } } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $Output + }) +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxAccountEnabled.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSharedMailboxAccountEnabled.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxAccountEnabled.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSharedMailboxAccountEnabled.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-RemoveApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-RemoveApp.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemoveApp.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-RemoveApp.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSyncAPDevices.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ExecSyncAPDevices.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSyncAPDevices.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ExecSyncAPDevices.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAutopilotconfig.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ListAutopilotconfig.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListAutopilotconfig.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ListAutopilotconfig.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-RemoveAPDevice.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-RemoveAPDevice.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemoveAPDevice.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-RemoveAPDevice.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGroups.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroups.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListGroups.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroups.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecRestoreDeleted.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecRestoreDeleted.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ExecRestoreDeleted.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecRestoreDeleted.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDeletedItems.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListDeletedItems.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListDeletedItems.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListDeletedItems.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAzureADConnectStatus.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Reports/Invoke-ListAzureADConnectStatus.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListAzureADConnectStatus.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Reports/Invoke-ListAzureADConnectStatus.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListInactiveAccounts.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Reports/Invoke-ListInactiveAccounts.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListInactiveAccounts.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Reports/Invoke-ListInactiveAccounts.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMFAUsers.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Reports/Invoke-ListMFAUsers.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListMFAUsers.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Reports/Invoke-ListMFAUsers.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSignIns.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Reports/Invoke-ListSignIns.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListSignIns.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Reports/Invoke-ListSignIns.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListLicenses.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Reports/Invoke-ListLicenses.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListLicenses.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Reports/Invoke-ListLicenses.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListOAuthApps.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Reports/Invoke-ListOAuthApps.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListOAuthApps.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Reports/Invoke-ListOAuthApps.ps1 From dd4ac1e841948a4bead18a46d16896cf735d8a0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 17 Feb 2025 21:37:37 +0100 Subject: [PATCH 018/167] Refactor Invoke-EditSpamFilter and Invoke-RemoveSpamfilter for improved logging and error handling --- .../Email-Exchange/Invoke-EditSpamFilter.ps1 | 30 ++++++++++-------- .../Public/Invoke-RemoveSpamfilter.ps1 | 31 ++++++++++--------- 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSpamFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSpamFilter.ps1 index f4bcef687f68..7559e53ab41c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSpamFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSpamFilter.ps1 @@ -11,26 +11,30 @@ Function Invoke-EditSpamFilter { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - $Tenantfilter = $request.Query.tenantfilter + Write-LogMessage -headers $Request.Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - $Params = @{ - Identity = $request.query.name - } + $TenantFilter = $request.Query.tenantFilter + $Name = $Request.Query.name ?? $Request.Body.name + $State = $State ?? $Request.Body.state try { - $cmdlet = if ($request.query.state -eq 'enable') { 'Enable-HostedContentFilterRule' } else { 'Disable-HostedContentFilterRule' } - $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet $cmdlet -cmdParams $params -useSystemmailbox $true - $Result = "Set Spamfilter rule to $($request.query.State)" - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $tenantfilter -message "Set Spamfilter rule $($Request.query.name) to $($request.query.State)" -sev Info + $Params = @{ + Identity = $Name + } + $Cmdlet = if ($State -eq 'enable') { 'Enable-HostedContentFilterRule' } else { 'Disable-HostedContentFilterRule' } + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet $Cmdlet -cmdParams $Params -useSystemMailbox $true + $Result = "Set Spamfilter rule $($Name) to $($State)" + Write-LogMessage -headers $Request.Headers -API $APIName -tenant $TenantFilter -message $Result -sev Info + $StatusCode = [HttpStatusCode]::OK } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $tenantfilter -message "Failed setting Spamfilter rule $($Request.query.guid) to $($request.query.State). Error:$ErrorMessage" -Sev 'Error' - $Result = $ErrorMessage + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed setting Spamfilter rule $($Name) to $($State). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Request.Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::Forbidden } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK + StatusCode = $StatusCode Body = @{Results = $Result } }) diff --git a/Modules/CIPPCore/Public/Invoke-RemoveSpamfilter.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveSpamfilter.ps1 index c67bf676a579..8e8d6c1063b6 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveSpamfilter.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveSpamfilter.ps1 @@ -12,28 +12,31 @@ Function Invoke-RemoveSpamfilter { $APIName = $Request.Params.CIPPEndpoint $User = $Request.Headers - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' - $Tenantfilter = $request.Query.tenantfilter + Write-LogMessage -Headers $User -API $APIName -message 'Accessed this API' -Sev 'Debug' + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Query.tenantFilter + $Name = $Request.Query.name ?? $Request.Body.name - $Params = @{ - Identity = $request.query.name - } try { - $cmdlet = 'Remove-HostedContentFilterRule' - $null = New-ExoRequest -tenantid $Tenantfilter -cmdlet $cmdlet -cmdParams $params -useSystemmailbox $true - $cmdlet = 'Remove-HostedContentFilterPolicy' - $null = New-ExoRequest -tenantid $Tenantfilter -cmdlet $cmdlet -cmdParams $params -useSystemmailbox $true - $Result = "Deleted $($Request.query.name)" - Write-LogMessage -Headers $User -API 'TransportRules' -tenant $tenantfilter -message "Deleted transport rule $($Request.query.name)" -sev Debug + $Params = @{ + Identity = $Name + } + $Cmdlet = 'Remove-HostedContentFilterRule' + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet $Cmdlet -cmdParams $Params -useSystemMailbox $true + $Cmdlet = 'Remove-HostedContentFilterPolicy' + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet $Cmdlet -cmdParams $Params -useSystemMailbox $true + $Result = "Deleted Spam filter rule $($Name)" + Write-LogMessage -Headers $User -API $APIName -tenant $TenantFilter -message $Result -Sev Info + $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API 'TransportRules' -tenant $tenantfilter -message "Failed deleting transport rule $($Request.query.name). Error:$($ErrorMessage.NormalizedError)" -Sev Error -LogData $ErrorMessage - $Result = $ErrorMessage + $Result = "Failed to delete Spam filter rule $($Name) - $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $User -API $APIName -tenant $TenantFilter -message $Result -Sev Error -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::Forbidden } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK + StatusCode = $StatusCode Body = @{Results = $Result } }) From 7b6b71cd8225a2d2fa2e69681d6079161cf7386a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 17 Feb 2025 21:47:03 +0100 Subject: [PATCH 019/167] Enhance Invoke-ExecRemoveMailboxRule and Remove-CIPPMailboxRule for improved parameter handling and logging --- .../Invoke-ExecRemoveMailboxRule.ps1 | 19 ++++++++----------- .../Public/Remove-CIPPMailboxRule.ps1 | 2 +- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecRemoveMailboxRule.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecRemoveMailboxRule.ps1 index 530767520c08..4ae271d4bf4d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecRemoveMailboxRule.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecRemoveMailboxRule.ps1 @@ -10,20 +10,17 @@ Function Invoke-ExecRemoveMailboxRule { [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = 'Remove mailbox rule' - $TenantFilter = $Request.Query.TenantFilter - $RuleName = $Request.Query.ruleName - $RuleId = $Request.Query.ruleId - $Username = $Request.Query.userPrincipalName + $APIName = $Request.Params.CIPPEndpoint + $TenantFilter = $Request.Query.TenantFilter ?? $Request.Query.TenantFilter + $RuleName = $Request.Query.ruleName ?? $Request.Body.ruleName + $RuleId = $Request.Query.ruleId ?? $Request.Body.ruleId + $Username = $Request.Query.userPrincipalName ?? $Request.Body.userPrincipalName - $User = $Request.Headers - Write-LogMessage -Headers $User -API $APINAME -tenant $TenantFilter -message 'Accessed this API' -Sev 'Debug' - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + $Headers = $Request.Headers + Write-LogMessage -Headers $Headers -API $APIName -tenant $TenantFilter -message 'Accessed this API' -Sev 'Debug' # Remove the rule - $Results = Remove-CIPPMailboxRule -userid $User -username $Username -TenantFilter $TenantFilter -APIName $APINAME -Headers $User -RuleId $RuleId -RuleName $RuleName + $Results = Remove-CIPPMailboxRule -username $Username -TenantFilter $TenantFilter -APIName $APIName -Headers $Headers -RuleId $RuleId -RuleName $RuleName if ($Results -like '*Could not delete*') { $StatusCode = [HttpStatusCode]::Forbidden diff --git a/Modules/CIPPCore/Public/Remove-CIPPMailboxRule.ps1 b/Modules/CIPPCore/Public/Remove-CIPPMailboxRule.ps1 index 47b494ac4b7c..fbc5cd2d436e 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPMailboxRule.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPMailboxRule.ps1 @@ -22,7 +22,7 @@ function Remove-CIPPMailboxRule { return "No rules for $($username) to delete" } else { ForEach ($rule in $rules) { - New-ExoRequest -tenantid $TenantFilter -cmdlet 'Remove-InboxRule' -Anchor $username -cmdParams @{Identity = $rule.Identity } + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Remove-InboxRule' -Anchor $username -cmdParams @{Identity = $rule.Identity } } Write-LogMessage -headers $Headers -API $APIName -message "Deleted Rules for $($username)" -Sev 'Info' -tenant $TenantFilter return "Deleted Rules for $($username)" From 4b2894077ad65f258cb2d80e07523f03d4de36c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 17 Feb 2025 21:53:45 +0100 Subject: [PATCH 020/167] Fix casing and improve comments in Invoke-ExecSendPush function for consistency and clarity --- .../Administration/Users/Invoke-ExecSendPush.ps1 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecSendPush.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecSendPush.ps1 index d077f97949bb..9eb13dbf1bfc 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecSendPush.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecSendPush.ps1 @@ -18,7 +18,7 @@ Function Invoke-ExecSendPush { $MFAAppID = '981f26a1-7f43-403b-a875-f8b09b8cd720' # Function to keep trying to get the access token while we wait for MS to actually set the temp password - function get-clientaccess { + function Get-ClientAccess { param( $uri, $body, @@ -31,7 +31,7 @@ Function Invoke-ExecSendPush { $count++ Start-Sleep 1 - $ClientToken = get-clientaccess -uri $uri -body $body -count $count + $ClientToken = Get-ClientAccess -uri $uri -body $body -count $count } else { Throw "Could not get Client Token: $_" } @@ -46,7 +46,7 @@ Function Invoke-ExecSendPush { # Check if we have one for the MFA App $SPID = ($SPResult | Where-Object { $_.appId -eq $MFAAppID }).id - # Create a serivce principal if needed + # Create a service principal if needed if (!$SPID) { $SPBody = [pscustomobject]@{ @@ -59,8 +59,8 @@ Function Invoke-ExecSendPush { $PassReqBody = @{ 'passwordCredential' = @{ 'displayName' = 'MFA Temporary Password' - 'endDateTime' = $(((Get-Date).addminutes(5))) - 'startDateTime' = $((Get-Date).addminutes(-5)) + 'endDateTime' = $((Get-Date).AddMinutes(5)) + 'startDateTime' = $((Get-Date).AddMinutes(-5)) } } | ConvertTo-Json -Depth 5 @@ -90,7 +90,7 @@ Function Invoke-ExecSendPush { # Attempt to get a token using the temp password $ClientUri = "https://login.microsoftonline.com/$TenantFilter/oauth2/token" try { - $ClientToken = get-clientaccess -Uri $ClientUri -Body $body + $ClientToken = Get-ClientAccess -Uri $ClientUri -Body $body } catch { $Body = 'Failed to create temporary token for MFA Application. Error: ' + $_.Exception.Message } @@ -107,7 +107,7 @@ Function Invoke-ExecSendPush { $colour = 'success' } if ($obj.BeginTwoWayAuthenticationResponse.AuthenticationResult -ne $true) { - $Body = "Authentication Failed! Does the user have Push/Phone call MFA configured? Errorcode: $($obj.BeginTwoWayAuthenticationResponse.result.value | Out-String)" + $Body = "Authentication Failed! Does the user have Push/Phone call MFA configured? ErrorCode: $($obj.BeginTwoWayAuthenticationResponse.result.value | Out-String)" $colour = 'error' } From bf967667ef8095a5a070c1ae86f81a9ce9586ebf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 17 Feb 2025 22:04:42 +0100 Subject: [PATCH 021/167] Refactor Invoke-ExecEnableArchive for improved error handling and parameter management --- .../Invoke-ExecEnableArchive.ps1 | 19 ++++++++-------- .../Public/Set-CIPPMailboxArchive.ps1 | 22 +++++++++---------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEnableArchive.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEnableArchive.ps1 index 599b50ee0f34..fe7b1811a419 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEnableArchive.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEnableArchive.ps1 @@ -13,21 +13,22 @@ Function Invoke-ExecEnableArchive { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - - # Interact with query parameters or the body of the request. + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $ID = $Request.Query.id ?? $Request.Body.id + Try { - $ResultsArch = Set-CIPPMailboxArchive -userid $Request.query.id -tenantFilter $Request.query.TenantFilter -APIName $APINAME -Headers $Request.Headers -ArchiveEnabled $true - $Results = [pscustomobject]@{'Results' = "$ResultsArch" } + $ResultsArch = Set-CIPPMailboxArchive -userid $ID -tenantFilter $TenantFilter -APIName $APINAME -Headers $Request.Headers -ArchiveEnabled $true + if ($ResultsArch -like 'Failed to set archive*') { throw $ResultsArch } + $StatusCode = [HttpStatusCode]::OK } catch { - $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" } + $ResultsArch = $_.Exception.Message + $StatusCode = [HttpStatusCode]::InternalServerError } + $Results = [pscustomobject]@{'Results' = "$ResultsArch" } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK + StatusCode = $StatusCode Body = $Results }) diff --git a/Modules/CIPPCore/Public/Set-CIPPMailboxArchive.ps1 b/Modules/CIPPCore/Public/Set-CIPPMailboxArchive.ps1 index c21505e27310..134dd48fb958 100644 --- a/Modules/CIPPCore/Public/Set-CIPPMailboxArchive.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPMailboxArchive.ps1 @@ -2,23 +2,23 @@ function Set-CIPPMailboxArchive { [CmdletBinding()] param ( $Headers, - $userid, - $username, + $UserID, + $Username, $APIName = 'Mailbox Archive', $TenantFilter, [bool]$ArchiveEnabled ) - $User = $Request.Headers - - Try { - if (!$username) { $username = $userid } - $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Enable-Mailbox' -cmdParams @{Identity = $userid; Archive = $ArchiveEnabled } - "Successfully set archive for $username to $ArchiveEnabled" - Write-LogMessage -Headers $User -API $APINAME -tenant $($tenantfilter) -message "Successfully set archive for $username to $ArchiveEnabled" -Sev 'Info' + try { + if (!$Username) { $Username = $UserID } + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Enable-Mailbox' -cmdParams @{Identity = $UserID; Archive = $ArchiveEnabled } + $Message = "Successfully set archive for $Username to $ArchiveEnabled" + Write-LogMessage -Headers $Headers -API $APINAME -tenant $TenantFilter -message $Message -Sev 'Info' + return $Message } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -tenant $($tenantfilter) -message "Failed to set archive for $username. Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage - "Failed. $($ErrorMessage.NormalizedError)" + $Message = "Failed to set archive for $Username. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Headers -API $APINAME -tenant $TenantFilter -message $Message -Sev 'Error' -LogData $ErrorMessage + return $Message } } From 735d61ac781851b56b25679465a9cc325cbd831b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 17 Feb 2025 22:18:01 +0100 Subject: [PATCH 022/167] Refactor Invoke-ExecDisableUser and Set-CIPPSignInState for improved parameter handling, logging, and error management --- .../Users/Invoke-ExecDisableUser.ps1 | 21 ++++++++++++++----- .../CIPPCore/Public/Set-CIPPSignInState.ps1 | 12 +++++------ 2 files changed, 22 insertions(+), 11 deletions(-) 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 31aeb9f5d45f..67a2b036cffb 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 @@ -11,17 +11,28 @@ Function Invoke-ExecDisableUser { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint + $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. + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $ID = $Request.Query.ID ?? $Request.Body.ID + $Enable = $Request.Query.Enable ?? $Request.Body.Enable + $Enable = [System.Convert]::ToBoolean($Enable) + try { - $State = Set-CIPPSignInState -userid $Request.query.ID -TenantFilter $Request.Query.TenantFilter -APIName $APINAME -Headers $Request.Headers -AccountEnabled ([System.Convert]::ToBoolean($Request.Query.Enable)) - $Results = [pscustomobject]@{'Results' = "$State" } + $Result = Set-CIPPSignInState -UserID $ID -TenantFilter $TenantFilter -APIName $APIName -Headers $Headers -AccountEnabled $Enable + if ($Result -like 'Could not disable*' -or $Result -like 'WARNING: User is AD Sync enabled*') { throw $Result } + $StatusCode = [HttpStatusCode]::OK } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - $Results = [pscustomobject]@{'Results' = "Failed. $ErrorMessage" } + $Result = $_.Exception.Message + $StatusCode = [HttpStatusCode]::InternalServerError } + $Results = [pscustomobject]@{'Results' = "$Result" } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK + StatusCode = $StatusCode Body = $Results }) diff --git a/Modules/CIPPCore/Public/Set-CIPPSignInState.ps1 b/Modules/CIPPCore/Public/Set-CIPPSignInState.ps1 index f3a51da6934b..bf2266cae08b 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', @@ -13,19 +13,19 @@ function Set-CIPPSignInState { accountEnabled = [bool]$AccountEnabled } $body = ConvertTo-Json -InputObject $body -Compress -Depth 5 - $UserDetails = New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/users/$($UserId)?`$select=onPremisesSyncEnabled" -noPagination $true -tenantid $TenantFilter -verbose - $null = New-GraphPostRequest -uri "https://graph.microsoft.com/v1.0/users/$($UserId)" -tenantid $TenantFilter -type PATCH -body $body -verbose - Write-LogMessage -headers $Headers -API $APIName -message "Set account enabled state to $AccountEnabled for $UserId" -Sev 'Info' -tenant $TenantFilter + $UserDetails = New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/users/$($UserID)?`$select=onPremisesSyncEnabled" -noPagination $true -tenantid $TenantFilter -verbose + $null = New-GraphPostRequest -uri "https://graph.microsoft.com/v1.0/users/$($UserID)" -tenantid $TenantFilter -type PATCH -body $body -verbose + Write-LogMessage -headers $Headers -API $APIName -message "Set account enabled state to $AccountEnabled for $UserID" -Sev 'Info' -tenant $TenantFilter if ($UserDetails.onPremisesSyncEnabled -eq $true) { return 'WARNING: User is AD Sync enabled. Please enable/disable in AD.' } else { - return "Set account enabled state to $AccountEnabled for $UserId" + return "Set account enabled state to $AccountEnabled for $UserID" } } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers -API $APIName -message "Could not disable sign in for $UserId. Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + Write-LogMessage -headers $Headers -API $APIName -message "Could not disable sign in for $UserID. Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage return "Could not disable $UserId. Error: $($ErrorMessage.NormalizedError)" } } From 6a3f4b8f960338f56e0ed6e9d61625427bb0ed24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 17 Feb 2025 22:30:52 +0100 Subject: [PATCH 023/167] Refactor Invoke-ExecResetPass for improved parameter handling, error management, and logging --- .../Users/Invoke-ExecResetPass.ps1 | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetPass.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetPass.ps1 index 60f78066ef3b..286e6ac73bf1 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetPass.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetPass.ps1 @@ -14,25 +14,28 @@ Function Invoke-ExecResetPass { Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - Write-Host "$($Request.query.ID)" # Interact with query parameters or the body of the request. - $TenantFilter = $Request.Query.TenantFilter - $mustChange = [System.Convert]::ToBoolean($request.query.MustChange) + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $ID = $Request.Query.ID ?? $Request.Body.ID + $DisplayName = $Request.Query.displayName ?? $Request.Body.displayName + $MustChange = $Request.Query.MustChange ?? $Request.Body.MustChange + $MustChange = [System.Convert]::ToBoolean($MustChange) try { - $Reset = Set-CIPPResetPassword -userid $Request.query.ID -tenantFilter $TenantFilter -APIName $APINAME -Headers $Request.Headers -forceChangePasswordNextSignIn $mustChange - $Results = [pscustomobject]@{'Results' = $Reset } + $Result = Set-CIPPResetPassword -UserID $ID -tenantFilter $TenantFilter -APIName $APINAME -Headers $Request.Headers -forceChangePasswordNextSignIn $MustChange + if ($Result.state -eq 'Error') { throw $Result.resultText } + $StatusCode = [HttpStatusCode]::OK } catch { - $Results = [pscustomobject]@{'Results' = "Failed to reset password for $($Request.query.displayName): $($_.Exception.Message)" } - Write-LogMessage -headers $Request.Headers -API $APINAME -message "Failed to reset password for $($Request.query.displayName): $($_.Exception.Message)" -Sev 'Error' + $Result = $_.Exception.Message + Write-LogMessage -headers $Request.Headers -API $APINAME -message $Result -Sev 'Error' + $StatusCode = [HttpStatusCode]::InternalServerError } + $Results = [pscustomobject]@{'Results' = $Result } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK + StatusCode = $StatusCode Body = $Results }) From ea8e73454734899aaffd043bc5fdd1aefbef37d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 17 Feb 2025 22:43:10 +0100 Subject: [PATCH 024/167] Refactor Invoke-ExecRevokeSessions and Revoke-CIPPSessions for improved parameter handling, error management, and logging Casing and add displayName param --- .../Users/Invoke-ExecResetPass.ps1 | 2 +- .../Users/Invoke-ExecRevokeSessions.ps1 | 16 +++++++++++----- .../CIPPCore/Public/Revoke-CIPPSessions.ps1 | 6 +++--- .../CIPPCore/Public/Set-CIPPResetPassword.ps1 | 19 ++++++++++--------- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetPass.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetPass.ps1 index 286e6ac73bf1..53f86a6975c5 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetPass.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetPass.ps1 @@ -22,7 +22,7 @@ Function Invoke-ExecResetPass { $MustChange = [System.Convert]::ToBoolean($MustChange) try { - $Result = Set-CIPPResetPassword -UserID $ID -tenantFilter $TenantFilter -APIName $APINAME -Headers $Request.Headers -forceChangePasswordNextSignIn $MustChange + $Result = Set-CIPPResetPassword -UserID $ID -tenantFilter $TenantFilter -APIName $APINAME -Headers $Request.Headers -forceChangePasswordNextSignIn $MustChange -DisplayName $DisplayName if ($Result.state -eq 'Error') { throw $Result.resultText } $StatusCode = [HttpStatusCode]::OK } catch { 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 0c1b8bc5210d..b09d8a09fa4b 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 @@ -14,17 +14,23 @@ Function Invoke-ExecRevokeSessions { Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' # Interact with query parameters or the body of the request. - $TenantFilter = $Request.Query.TenantFilter + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $ID = $Request.Query.id ?? $Request.Body.id + $Username = $Request.Query.Username ?? $Request.Body.Username + try { - $RevokeSessions = Revoke-CIPPSessions -userid $Request.Query.id -tenantFilter $TenantFilter -username $Request.Query.Username -APIName $APINAME -Headers $Request.Headers - $Results = [pscustomobject]@{'Results' = $RevokeSessions } + $Result = Revoke-CIPPSessions -UserID $ID -TenantFilter $TenantFilter -Username $Username -APIName $APIName -Headers $Request.Headers + if ($Result -like 'Revoke Session Failed*') { throw $Result } + $StatusCode = [HttpStatusCode]::OK } catch { - $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" } + $Result = $_.Exception.Message + $StatusCode = [HttpStatusCode]::InternalServerError } + $Results = [pscustomobject]@{'Results' = $Result } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK + StatusCode = $StatusCode Body = $Results }) diff --git a/Modules/CIPPCore/Public/Revoke-CIPPSessions.ps1 b/Modules/CIPPCore/Public/Revoke-CIPPSessions.ps1 index 82ee5126cd4c..a7f37e6e7854 100644 --- a/Modules/CIPPCore/Public/Revoke-CIPPSessions.ps1 +++ b/Modules/CIPPCore/Public/Revoke-CIPPSessions.ps1 @@ -2,14 +2,14 @@ function Revoke-CIPPSessions { [CmdletBinding()] param ( $Headers, - $userid, - $username, + $UserID, + $Username, $APIName = 'Revoke Sessions', $TenantFilter ) try { - $GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($userid)/invalidateAllRefreshTokens" -tenantid $TenantFilter -type POST -body '{}' -verbose + $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($userid)/invalidateAllRefreshTokens" -tenantid $TenantFilter -type POST -body '{}' -verbose Write-LogMessage -headers $Headers -API $APIName -message "Revoked sessions for $($username)" -Sev 'Info' -tenant $TenantFilter return "Success. All sessions by $username have been revoked" diff --git a/Modules/CIPPCore/Public/Set-CIPPResetPassword.ps1 b/Modules/CIPPCore/Public/Set-CIPPResetPassword.ps1 index 74d248789127..ff87694f31f0 100644 --- a/Modules/CIPPCore/Public/Set-CIPPResetPassword.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPResetPassword.ps1 @@ -1,8 +1,9 @@ function Set-CIPPResetPassword { [CmdletBinding()] param( - $userid, - $tenantFilter, + $UserID, + $DisplayName, + $TenantFilter, $APIName = 'Reset Password', $Headers, [bool]$forceChangePasswordNextSignIn = $true @@ -17,32 +18,32 @@ function Set-CIPPResetPassword { } } | ConvertTo-Json -Compress - $UserDetails = New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/users/$($UserId)?`$select=onPremisesSyncEnabled" -noPagination $true -tenantid $TenantFilter -verbose - $null = New-GraphPostRequest -uri "https://graph.microsoft.com/v1.0/users/$($userid)" -tenantid $TenantFilter -type PATCH -body $passwordProfile -verbose + $UserDetails = New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/users/$($UserID)?`$select=onPremisesSyncEnabled" -noPagination $true -tenantid $TenantFilter -verbose + $null = New-GraphPostRequest -uri "https://graph.microsoft.com/v1.0/users/$($UserID)" -tenantid $TenantFilter -type PATCH -body $passwordProfile -verbose #PWPush $PasswordLink = New-PwPushLink -Payload $password if ($PasswordLink) { $password = $PasswordLink } - Write-LogMessage -headers $Headers -API $APIName -message "Reset the password for $($userid). User must change password is set to $forceChangePasswordNextSignIn" -Sev 'Info' -tenant $TenantFilter + Write-LogMessage -headers $Headers -API $APIName -message "Reset the password for $DisplayName, $($UserID). User must change password is set to $forceChangePasswordNextSignIn" -Sev 'Info' -tenant $TenantFilter if ($UserDetails.onPremisesSyncEnabled -eq $true) { - return [pscustomobject]@{ resultText = "Reset the password for $($userid). User must change password is set to $forceChangePasswordNextSignIn. The new password is $password. WARNING: This user is AD synced. Please confirm passthrough or writeback is enabled." + return [pscustomobject]@{ resultText = "Reset the password for $DisplayName, $($UserID). User must change password is set to $forceChangePasswordNextSignIn. The new password is $password. WARNING: This user is AD synced. Please confirm passthrough or writeback is enabled." copyField = $password state = 'warning' } } else { - return [pscustomobject]@{ resultText = "Reset the password for $($userid). User must change password is set to $forceChangePasswordNextSignIn. The new password is $password" + return [pscustomobject]@{ resultText = "Reset the password for $DisplayName, $($UserID). User must change password is set to $forceChangePasswordNextSignIn. The new password is $password" copyField = $password state = 'success' } } } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers -API $APIName -message "Could not reset password for $($userid). Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + Write-LogMessage -headers $Headers -API $APIName -message "Could not reset password for $DisplayName, $($UserID). Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage return [pscustomobject]@{ - resultText = "Could not reset password for $($userid). Error: $($ErrorMessage.NormalizedError)" + resultText = "Could not reset password for $DisplayName, $($UserID). Error: $($ErrorMessage.NormalizedError)" state = 'Error' } } From 31bc097f520ba0d31a152a38201db7ec1a52a7d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 17 Feb 2025 22:51:01 +0100 Subject: [PATCH 025/167] Refactor Invoke-RemoveUser for improved parameter handling, logging, and error management --- Modules/CIPPCore/Public/Invoke-RemoveUser.ps1 | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/Modules/CIPPCore/Public/Invoke-RemoveUser.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveUser.ps1 index 264aeaf9ec9f..816bf4c5bfab 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveUser.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveUser.ps1 @@ -11,30 +11,31 @@ Function Invoke-RemoveUser { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $User = $Request.Headers - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $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. - $TenantFilter = $Request.Query.TenantFilter - $userid = $Request.Query.ID - if (!$userid) { exit } + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $UserID = $Request.Query.ID ?? $Request.Body.ID + + if (!$UserID) { exit } try { - $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($userid)" -type DELETE -tenant $TenantFilter - Write-LogMessage -Headers $User -API $APINAME -message "Deleted $userid" -Sev 'Info' -tenant $TenantFilter - $body = [pscustomobject]@{'Results' = 'Successfully deleted the user.' } + $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($UserID)" -type DELETE -tenant $TenantFilter + $Result = "Successfully deleted $UserID." + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev 'Info' -tenant $TenantFilter + $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -message "Could not delete user $userid. $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - $body = [pscustomobject]@{'Results' = "Could not delete user: $($ErrorMessage.NormalizedError)" } - + $Result = "Could not delete user $($UserID). $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } + $Body = [pscustomobject]@{ 'Results' = $Result } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body + StatusCode = $StatusCode + Body = $Body }) - - } From ca8aa4675a505b2f669eab67dd67ea9bfb5a7362 Mon Sep 17 00:00:00 2001 From: Esco Date: Mon, 17 Feb 2025 14:56:51 +0100 Subject: [PATCH 026/167] feat: New MDM User Scope standard --- Modules/CIPPCore/Public/SAMManifest.json | 4 + .../Standards/Invoke-CIPPStandardMDMScope.ps1 | 124 ++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMDMScope.ps1 diff --git a/Modules/CIPPCore/Public/SAMManifest.json b/Modules/CIPPCore/Public/SAMManifest.json index 65b801589a7f..a76e42384a22 100644 --- a/Modules/CIPPCore/Public/SAMManifest.json +++ b/Modules/CIPPCore/Public/SAMManifest.json @@ -554,6 +554,10 @@ { "id": "b7887744-6746-4312-813d-72daeaee7e2d", "type": "Scope" + }, + { + "id": "a8ead177-1889-4546-9387-f25e658e2a79", + "type": "Scope" } ] }, diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMDMScope.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMDMScope.ps1 new file mode 100644 index 000000000000..81e588624756 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMDMScope.ps1 @@ -0,0 +1,124 @@ +function Invoke-CIPPStandardMDMScope { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) MDMScope + .SYNOPSIS + (Label) Configure MDM user scope + .DESCRIPTION + (Helptext) Configures the MDM user scope. This also sets the terms of use, discovery and compliance URL to default URLs. + (DocsDescription) Configures the MDM user scope. This also sets the terms of use URL, discovery URL and compliance URL to default values. + .NOTES + CAT + Intune Standards + TAG + ADDEDCOMPONENT + {"name":"appliesTo","label":"MDM User Scope?","type":"radio","options":[{"label":"All","value":"all"},{"label":"None","value":"none"},{"label":"Custom Group","value":"selected"}]} + {"type":"textField","name":"standards.MDMScope.customGroup","label":"Custom Group Name","required":false} + IMPACT + Low Impact + POWERSHELLEQUIVALENT + Graph API + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/intune-standards#low-impact + #> + + param($Tenant, $Settings) + + $CurrentInfo = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/policies/mobileDeviceManagementPolicies/0000000a-0000-0000-c000-000000000000?$expand=includedGroups' -tenantid $Tenant + + $StateIsCorrect = ($CurrentInfo.termsOfUseUrl -eq 'https://portal.manage.microsoft.com/TermsofUse.aspx') -and + ($CurrentInfo.discoveryUrl -eq 'https://enrollment.manage.microsoft.com/enrollmentserver/discovery.svc') -and + ($CurrentInfo.complianceUrl -eq 'https://portal.manage.microsoft.com/?portalAction=Compliance') -and + ($CurrentInfo.appliesTo -eq $Settings.appliesTo) -and + ($Settings.appliesTo -ne 'selected' -or ($CurrentInfo.includedGroups.displayName -contains $Settings.customGroup)) + + If ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'MDM Scope already correctly configured' -sev Info + } else { + $GraphParam = @{ + tenantid = $tenant + Uri = 'https://graph.microsoft.com/beta/policies/mobileDeviceManagementPolicies/0000000a-0000-0000-c000-000000000000' + ContentType = 'application/json; charset=utf-8' + asApp = $false + type = 'PATCH' + AddedHeaders = @{'Accept-Language' = 0 } + Body = @{ + 'termsOfUseUrl' = 'https://portal.manage.microsoft.com/TermsofUse.aspx' + 'discoveryUrl' = 'https://enrollment.manage.microsoft.com/enrollmentserver/discovery.svc' + 'complianceUrl' = 'https://portal.manage.microsoft.com/?portalAction=Compliance' + } | ConvertTo-Json + } + + try { + New-GraphPostRequest @GraphParam + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Successfully configured MDM Scope' -sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to configure MDM Scope." -sev Error -LogData $ErrorMessage + } + + # Workaround for MDM Scope Assignment error: "Could not set MDM Scope for [TENANT]: Simultaneous patch requests on both the appliesTo and URL properties are currently not supported." + if ($Settings.appliesTo -ne 'selected') { + $GraphParam = @{ + tenantid = $tenant + Uri = 'https://graph.microsoft.com/beta/policies/mobileDeviceManagementPolicies/0000000a-0000-0000-c000-000000000000' + ContentType = 'application/json; charset=utf-8' + asApp = $false + type = 'PATCH' + AddedHeaders = @{'Accept-Language' = 0 } + Body = @{ + 'appliesTo' = $Settings.appliesTo + } | ConvertTo-Json + } + + try { + New-GraphPostRequest @GraphParam + Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully assigned $($Settings.appliesTo) to MDM Scope" -sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to assign $($Settings.appliesTo) to MDM Scope." -sev Error -LogData $ErrorMessage + } + } else { + $GroupID = (New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/groups?`$top=999&`$select=id,displayName&`$filter=displayName eq '$($Settings.customGroup)'" -tenantid $tenant -asApp $true).id + $GraphParam = @{ + tenantid = $tenant + Uri = 'https://graph.microsoft.com/beta/policies/mobileDeviceManagementPolicies/0000000a-0000-0000-c000-000000000000/includedGroups/$ref' + ContentType = 'application/json; charset=utf-8' + asApp = $false + type = 'POST' + AddedHeaders = @{'Accept-Language' = 0 } + Body = @{ + '@odata.id' = "https://graph.microsoft.com/odata/groups('$GroupID')" + } | ConvertTo-Json + } + + try { + New-GraphPostRequest @GraphParam + Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully assigned $($Settings.customGroup) to MDM Scope" -sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to assign $($Settings.customGroup) to MDM Scope" -sev Error -LogData $ErrorMessage + } + } + } + } + + if ($Settings.alert -eq $true -eq $true) { + if ($StateIsCorrect) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'MDM Scope is correctly configured' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'MDM Scope is not correctly configured' -sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'MDMScope' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant + } + +} From 59bf8e08881224cefcbce1d99567fcc0d2517018 Mon Sep 17 00:00:00 2001 From: Esco Date: Tue, 18 Feb 2025 13:51:47 +0100 Subject: [PATCH 027/167] feat: TeamsGlobalMeetingPolicy AllowExternalParticipantGiveRequestControl switch --- .../Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 index 4d0cfd8ff359..b1c8338346b0 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 @@ -35,13 +35,13 @@ Function Invoke-CIPPStandardTeamsGlobalMeetingPolicy { $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsMeetingPolicy' -CmdParams @{Identity = 'Global' } | Select-Object AllowAnonymousUsersToJoinMeeting, AllowAnonymousUsersToStartMeeting, AutoAdmittedUsers, AllowPSTNUsersToBypassLobby, MeetingChatEnabledType, DesignatedPresenterRoleMode, AllowExternalParticipantGiveRequestControl - $StateIsCorrect = ($CurrentState.AllowAnonymousUsersToJoinMeeting -eq $Settings.AllowAnonymousUsersToJoinMeeting) -and + $StateIsCorrect = ($CurrentState.AllowAnonymousUsersToJoinMeeting -eq $Settings.AllowAnonymousUsersToJoinMeeting) -and ($CurrentState.AllowAnonymousUsersToStartMeeting -eq $false) -and ($CurrentState.AutoAdmittedUsers -eq 'EveryoneInCompanyExcludingGuests') -and ($CurrentState.AllowPSTNUsersToBypassLobby -eq $false) -and ($CurrentState.MeetingChatEnabledType -eq $Settings.MeetingChatEnabledType.value) -and ($CurrentState.DesignatedPresenterRoleMode -eq $Settings.DesignatedPresenterRoleMode.value) -and - ($CurrentState.AllowExternalParticipantGiveRequestControl -eq $false) + ($CurrentState.AllowExternalParticipantGiveRequestControl -eq $Settings.AllowExternalParticipantGiveRequestControl) if ($Settings.remediate -eq $true) { if ($StateIsCorrect -eq $true) { @@ -55,7 +55,7 @@ Function Invoke-CIPPStandardTeamsGlobalMeetingPolicy { AllowPSTNUsersToBypassLobby = $false MeetingChatEnabledType = $Settings.MeetingChatEnabledType.value DesignatedPresenterRoleMode = $Settings.DesignatedPresenterRoleMode.value - AllowExternalParticipantGiveRequestControl = $false + AllowExternalParticipantGiveRequestControl = $Settings.AllowExternalParticipantGiveRequestControl } try { From f1e7549f3b2f5d7c6e84799ffe23fefe5d581e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Wed, 19 Feb 2025 21:33:49 +0100 Subject: [PATCH 028/167] Modernize and support POST --- .../CIPPCore/Public/Invoke-RemoveCAPolicy.ps1 | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/Modules/CIPPCore/Public/Invoke-RemoveCAPolicy.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveCAPolicy.ps1 index 9d5a9380afcb..7c894788f257 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveCAPolicy.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveCAPolicy.ps1 @@ -11,27 +11,28 @@ Function Invoke-RemoveCAPolicy { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $User = $Request.Headers - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $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. - $TenantFilter = $Request.Query.TenantFilter - $policyId = $Request.Query.GUID + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $policyId = $Request.Query.GUID ?? $Request.Body.GUID if (!$policyId) { exit } try { $null = New-GraphPostRequest -uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies/$($policyId)" -type DELETE -tenant $TenantFilter -asapp $true - Write-LogMessage -Headers $User -API $APINAME -message "Deleted CA Policy $policyId" -Sev 'Info' -tenant $TenantFilter - $body = [pscustomobject]@{'Results' = 'Successfully deleted the policy' } - + $Result = "Deleted CA Policy $($policyId)" + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev 'Info' -tenant $TenantFilter + $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -message "Could not delete CA policy $policyId. $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - $body = [pscustomobject]@{'Results' = "Could not delete policy: $($ErrorMessage.NormalizedError)" } - + $Result = "Could not delete CA policy with ID $($policyId) : $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::Forbidden } + $body = [pscustomobject]@{'Results' = $Result } Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK + StatusCode = $StatusCode Body = $body }) From 0b19f8af3e81b9329518021dc1e803ddee254e12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Wed, 19 Feb 2025 22:21:30 +0100 Subject: [PATCH 029/167] Modernize --- .../Public/Invoke-RemoveQueuedApp.ps1 | 22 +++++++++-------- .../Public/Invoke-RemoveSpamfilter.ps1 | 8 +++---- .../Invoke-RemoveSpamfilterTemplate.ps1 | 24 ++++++++++--------- .../Invoke-RemoveTransportRuleTemplate.ps1 | 18 +++++++------- 4 files changed, 39 insertions(+), 33 deletions(-) diff --git a/Modules/CIPPCore/Public/Invoke-RemoveQueuedApp.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveQueuedApp.ps1 index d4714f12dc55..4cbe632f33f3 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveQueuedApp.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveQueuedApp.ps1 @@ -11,26 +11,28 @@ Function Invoke-RemoveQueuedApp { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $User = $Request.Headers - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' + Write-LogMessage -Headers $Request.Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - $ID = $request.body.id + $ID = $request.body.ID try { $Table = Get-CippTable -tablename 'apps' - $Filter = "PartitionKey eq 'apps' and RowKey eq '$id'" + $Filter = "PartitionKey eq 'apps' and RowKey eq '$ID'" $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey - Remove-AzDataTableEntity -Force @Table -Entity $clearRow - Write-LogMessage -Headers $User -API $APINAME -message "Removed application queue for $ID." -Sev 'Info' - $body = [pscustomobject]@{'Results' = 'Successfully removed from queue.' } + Remove-AzDataTableEntity -Force @Table -Entity $ClearRow + $Message = "Removed application queue for $ID." + Write-LogMessage -Headers $Request.Headers -API $APIName -message $Message -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -message "Failed to remove application queue for $ID. $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage - $body = [pscustomobject]@{'Results' = "Failed to remove item. $(Get-NormalizedError -message $_.Exception.Message)" } + $Message = "Failed to remove application queue for $ID. $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Request.Headers -API $APIName -message $Message -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::Forbidden } + $body = [pscustomobject]@{'Results' = $Message } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK + StatusCode = $StatusCode Body = $body }) diff --git a/Modules/CIPPCore/Public/Invoke-RemoveSpamfilter.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveSpamfilter.ps1 index 8e8d6c1063b6..802139a386d7 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveSpamfilter.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveSpamfilter.ps1 @@ -11,8 +11,8 @@ Function Invoke-RemoveSpamfilter { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $User = $Request.Headers - Write-LogMessage -Headers $User -API $APIName -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -Headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' $TenantFilter = $Request.Query.tenantFilter ?? $Request.Query.tenantFilter $Name = $Request.Query.name ?? $Request.Body.name @@ -26,12 +26,12 @@ Function Invoke-RemoveSpamfilter { $Cmdlet = 'Remove-HostedContentFilterPolicy' $null = New-ExoRequest -tenantid $TenantFilter -cmdlet $Cmdlet -cmdParams $Params -useSystemMailbox $true $Result = "Deleted Spam filter rule $($Name)" - Write-LogMessage -Headers $User -API $APIName -tenant $TenantFilter -message $Result -Sev Info + Write-LogMessage -Headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev Info $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ $Result = "Failed to delete Spam filter rule $($Name) - $($ErrorMessage.NormalizedError)" - Write-LogMessage -Headers $User -API $APIName -tenant $TenantFilter -message $Result -Sev Error -LogData $ErrorMessage + Write-LogMessage -Headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev Error -LogData $ErrorMessage $StatusCode = [HttpStatusCode]::Forbidden } # Associate values to output bindings by calling 'Push-OutputBinding'. diff --git a/Modules/CIPPCore/Public/Invoke-RemoveSpamfilterTemplate.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveSpamfilterTemplate.ps1 index c66447217bff..e21d916ec5ee 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveSpamfilterTemplate.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveSpamfilterTemplate.ps1 @@ -11,28 +11,30 @@ Function Invoke-RemoveSpamfilterTemplate { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $User = $Request.Headers - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -Headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - $ID = $request.body.id + $ID = $Request.Body.ID try { $Table = Get-CippTable -tablename 'templates' - $Filter = "PartitionKey eq 'SpamfilterTemplate' and RowKey eq '$id'" + $Filter = "PartitionKey eq 'SpamfilterTemplate' and RowKey eq '$ID'" $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey - Remove-AzDataTableEntity -Force @Table -Entity $clearRow - Write-LogMessage -Headers $User -API $APINAME -message "Removed Spamfilter Template with ID $ID." -Sev 'Info' - $body = [pscustomobject]@{'Results' = 'Successfully Spamfilter template' } + Remove-AzDataTableEntity -Force @Table -Entity $ClearRow + $Result = "Removed Spamfilter template with ID $ID" + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -message "Failed to remove Spam filter Rule template $ID. $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage - $body = [pscustomobject]@{'Results' = "Failed to remove template: $($ErrorMessage.NormalizedError)" } + $Result = "Failed to remove Spam filter Rule template $ID. $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::Forbidden } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body + StatusCode = $StatusCode + Body = @{'Results' = $Result } }) diff --git a/Modules/CIPPCore/Public/Invoke-RemoveTransportRuleTemplate.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveTransportRuleTemplate.ps1 index a5b744b89b7f..7e24d5453f54 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveTransportRuleTemplate.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveTransportRuleTemplate.ps1 @@ -14,25 +14,27 @@ Function Invoke-RemoveTransportRuleTemplate { $User = $Request.Headers Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' - $ID = $request.query.id ?? $request.body.id + $ID = $request.query.ID ?? $request.body.ID try { $Table = Get-CippTable -tablename 'templates' $Filter = "PartitionKey eq 'TransportTemplate' and RowKey eq '$id'" $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey - Remove-AzDataTableEntity -Force @Table -Entity $clearRow - Write-LogMessage -Headers $User -API $APINAME -message "Removed Transport Rule Template with ID $ID." -Sev 'Info' - $body = [pscustomobject]@{'Results' = 'Successfully removed Transport Rule Template' } + Remove-AzDataTableEntity -Force @Table -Entity $ClearRow + $Result = "Removed Transport Rule Template with ID $ID." + Write-LogMessage -Headers $User -API $APINAME -message $Result -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -message "Failed to remove Transport Rule template $ID. $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage - $body = [pscustomobject]@{'Results' = "Failed to remove template: $($ErrorMessage.NormalizedError)" } + $Result = "Failed to remove Transport Rule template with ID $ID. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $User -API $APINAME -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::Forbidden } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body + StatusCode = $StatusCode + Body = @{ Results = $Result } }) From 7562863e7d612c17e5734568dc2e1c0b29f68782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Wed, 19 Feb 2025 22:28:28 +0100 Subject: [PATCH 030/167] Refactor Invoke-RemoveConnectionfilterTemplate for improved parameter handling, logging, and response management --- .../Invoke-RemoveConnectionfilterTemplate.ps1 | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Modules/CIPPCore/Public/Invoke-RemoveConnectionfilterTemplate.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveConnectionfilterTemplate.ps1 index a36d7a66d94e..c472b44a4382 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveConnectionfilterTemplate.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveConnectionfilterTemplate.ps1 @@ -11,28 +11,30 @@ Function Invoke-RemoveConnectionfilterTemplate { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $User = $Request.Headers - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -Headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - $ID = $request.body.id + $ID = $Request.body.ID try { $Table = Get-CippTable -tablename 'templates' - $Filter = "PartitionKey eq 'ConnectionfilterTemplate' and RowKey eq '$id'" + $Filter = "PartitionKey eq 'ConnectionfilterTemplate' and RowKey eq '$ID'" $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey - Remove-AzDataTableEntity -Force @Table -Entity $clearRow - Write-LogMessage -Headers $User -API $APINAME -message "Removed Connection Filter Template with ID $ID." -Sev 'Info' - $body = [pscustomobject]@{'Results' = 'Successfully removed Connection Filter Template' } + Remove-AzDataTableEntity -Force @Table -Entity $ClearRow + $Result = "Removed Connection Filter template with ID $($ID)" + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -message "Failed to remove Connection Filter template $ID. $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage - $body = [pscustomobject]@{'Results' = "Failed to remove template: $($ErrorMessage.NormalizedError)" } + $Result = "Failed to remove Connection Filter template with ID $ID. $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::Forbidden } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body + StatusCode = $StatusCode + Body = @{'Results' = $Result } }) From ad8b04fa9d09646fda62162fdbb068f20b4f0ab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Wed, 19 Feb 2025 23:03:45 +0100 Subject: [PATCH 031/167] Modernize --- .../Invoke-RemoveTenantAllowBlockList.ps1 | 31 +++++++++++-------- .../Public/Invoke-RemoveStandardTemplate.ps1 | 18 ++++++----- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1 index 84a81ea0f4cd..c02775315ee9 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1 @@ -11,23 +11,26 @@ Function Invoke-RemoveTenantAllowBlockList { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $TenantFilter = $Request.Body.tenantFilter + $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. + $Entries = $Request.Body.entries - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' try { - $listType = switch -Wildcard ($request.body.entries) { + $listType = switch -Wildcard ($Entries) { '*@*' { 'Sender'; break } '*.*' { 'Url'; break } default { 'FileHash' } } Write-Host "List type is $listType" $ExoRequest = @{ - tenantid = $Request.body.tenantfilter + tenantid = $TenantFilter cmdlet = 'Remove-TenantAllowBlockListItems' cmdParams = @{ - Entries = @($Request.body.entries) + Entries = @($Entries) ListType = $ListType } } @@ -35,19 +38,21 @@ Function Invoke-RemoveTenantAllowBlockList { $Results = New-ExoRequest @ExoRequest Write-Host $Results - $result = "Successfully removed $($Request.body.entries) from Block/Allow list" - Write-LogMessage -headers $Request.Headers -API $APIName -tenant $Request.query.tenantfilter -message $result -Sev 'Info' + $Result = "Successfully removed $($Entries) from Block/Allow list" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - $result = "Failed to remove $($Request.body.entries). Error: $ErrorMessage" - Write-LogMessage -headers $Request.Headers -API $APIName -tenant $Request.query.tenantfilter -message $result -Sev 'Error' + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed to remove $($Entries). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::Forbidden } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK + StatusCode = $StatusCode Body = @{ - 'Results' = $result + 'Results' = $Result 'Request' = $ExoRequest } }) diff --git a/Modules/CIPPCore/Public/Invoke-RemoveStandardTemplate.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveStandardTemplate.ps1 index 42f436018037..697c4e53a46a 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveStandardTemplate.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveStandardTemplate.ps1 @@ -11,8 +11,8 @@ Function Invoke-RemoveStandardTemplate { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $User = $Request.Headers - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -Headers $Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' $ID = $Request.Body.ID ?? $Request.Query.ID try { @@ -20,19 +20,21 @@ Function Invoke-RemoveStandardTemplate { $Filter = "PartitionKey eq 'StandardsTemplateV2' and RowKey eq '$id'" $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey Remove-AzDataTableEntity -Force @Table -Entity $clearRow - Write-LogMessage -Headers $User -API $APINAME -message "Removed Standards Template named $($ClearRow.name) and id $($id)" -Sev 'Info' - $body = [pscustomobject]@{'Results' = 'Successfully removed Template' } + $Result = "Removed Standards Template named $($ClearRow.name) and id $($id)" + Write-LogMessage -Headers $Headers -API $APINAME -message $Result -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -message "Failed to remove Standards template $ID. $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage - $body = [pscustomobject]@{'Results' = "Failed to remove template: $($ErrorMessage.NormalizedError)" } + $Result = "Failed to remove Standards template $ID. $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Headers -API $APINAME -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body + StatusCode = $StatusCode + Body = @{'Results' = $Result } }) From f366798fceadad2bb842f56b74caec9c95367061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Wed, 19 Feb 2025 23:37:33 +0100 Subject: [PATCH 032/167] Small bit of cleanup --- .../Public/CippQueue/Invoke-ListCippQueue.ps1 | 3 -- .../CippQueue/Invoke-RemoveCippQueue.ps1 | 3 -- .../Entrypoints/Invoke-ExecCSPLicense.ps1 | 29 ++++++++++--------- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/Modules/CIPPCore/Public/CippQueue/Invoke-ListCippQueue.ps1 b/Modules/CIPPCore/Public/CippQueue/Invoke-ListCippQueue.ps1 index 7738d9babd37..f4f80f4cb5dc 100644 --- a/Modules/CIPPCore/Public/CippQueue/Invoke-ListCippQueue.ps1 +++ b/Modules/CIPPCore/Public/CippQueue/Invoke-ListCippQueue.ps1 @@ -10,9 +10,6 @@ function Invoke-ListCippQueue { if ($Request) { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' } $CippQueue = Get-CippTable -TableName 'CippQueue' diff --git a/Modules/CIPPCore/Public/CippQueue/Invoke-RemoveCippQueue.ps1 b/Modules/CIPPCore/Public/CippQueue/Invoke-RemoveCippQueue.ps1 index afd30af62654..a9c2a9081c6a 100644 --- a/Modules/CIPPCore/Public/CippQueue/Invoke-RemoveCippQueue.ps1 +++ b/Modules/CIPPCore/Public/CippQueue/Invoke-RemoveCippQueue.ps1 @@ -10,9 +10,6 @@ function Invoke-RemoveCippQueue { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - $CippQueue = Get-CippTable -TableName 'CippQueue' Clear-AzDataTable @CippQueue $CippQueueTasks = Get-CippTable -TableName 'CippQueueTasks' diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecCSPLicense.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecCSPLicense.ps1 index c701bd475f40..0ba09a9db3ee 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecCSPLicense.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecCSPLicense.ps1 @@ -14,35 +14,36 @@ Function Invoke-ExecCSPLicense { Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - # Interact with query parameters or the body of the request. - $TenantFilter = $Request.body.TenantFilter - $Action = $Request.body.Action + $TenantFilter = $Request.Body.TenantFilter + $Action = $Request.Body.Action + $SKU = $Request.Body.SKU + try { if ($Action -eq 'Add') { - $GraphRequest = Set-SherwebSubscription -tenantFilter $TenantFilter -SKU $Request.body.sku -add $Request.body.Add + $null = Set-SherwebSubscription -tenantFilter $TenantFilter -SKU $SKU -add $Request.Body.Add } if ($Action -eq 'Remove') { - $GraphRequest = Set-SherwebSubscription -tenantFilter $TenantFilter -SKU $Request.body.sku -remove $Request.body.Remove + $null = Set-SherwebSubscription -tenantFilter $TenantFilter -SKU $SKU -remove $Request.Body.Remove } if ($Action -eq 'NewSub') { - $GraphRequest = Set-SherwebSubscription -tenantFilter $TenantFilter -SKU $Request.body.sku.value -Quantity $Request.body.Quantity + $null = Set-SherwebSubscription -tenantFilter $TenantFilter -SKU $SKU -Quantity $Request.Body.Quantity } if ($Action -eq 'Cancel') { - $GraphRequest = Remove-SherwebSubscription -tenantFilter $TenantFilter -SubscriptionIds $Request.body.SubscriptionIds + $null = Remove-SherwebSubscription -tenantFilter $TenantFilter -SubscriptionIds $Request.Body.SubscriptionIds } - $Message = 'License change executed successfully.' + $Result = 'License change executed successfully.' + $StatusCode = [HttpStatusCode]::OK } catch { - $Message = "Failed to execute license change. Error: $_" + $Result = "Failed to execute license change. Error: $_" + $StatusCode = [HttpStatusCode]::InternalServerError } - #If #GraphRequest is a GUID, the subscription was edited succesfully, and return that its done. + # If $GraphRequest is a GUID, the subscription was edited successfully, and return that it's done. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Message + StatusCode = $StatusCode + Body = $Result }) -Clobber } From 22d419ffda93ad8ecfc098285d6354d19632370e Mon Sep 17 00:00:00 2001 From: Esco Date: Wed, 19 Feb 2025 14:23:15 +0100 Subject: [PATCH 033/167] feat: InTune Template exclude --- .../Public/Set-CIPPAssignedPolicy.ps1 | 58 +++++++++++++------ .../CIPPCore/Public/Set-CIPPIntunePolicy.ps1 | 3 +- .../Invoke-CIPPStandardIntuneTemplate.ps1 | 2 +- 3 files changed, 43 insertions(+), 20 deletions(-) diff --git a/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 b/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 index 671daa0667fa..9b1714c3a6fe 100644 --- a/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 @@ -2,6 +2,7 @@ function Set-CIPPAssignedPolicy { [CmdletBinding(SupportsShouldProcess = $true)] param( $GroupName, + $excludeGroup, $PolicyId, $Type, $TenantFilter, @@ -11,25 +12,23 @@ function Set-CIPPAssignedPolicy { ) if (!$PlatformType) { $PlatformType = 'deviceManagement' } try { - $assignmentsObject = switch ($GroupName) { + $assignmentsObject = @() + + $assignmentsObject += switch ($GroupName) { 'allLicensedUsers' { - @( - @{ - target = @{ - '@odata.type' = '#microsoft.graph.allLicensedUsersAssignmentTarget' - } + @{ + target = @{ + '@odata.type' = '#microsoft.graph.allLicensedUsersAssignmentTarget' } - ) + } break } 'AllDevices' { - @( - @{ - target = @{ - '@odata.type' = '#microsoft.graph.allDevicesAssignmentTarget' - } + @{ + target = @{ + '@odata.type' = '#microsoft.graph.allDevicesAssignmentTarget' } - ) + } break } 'AllDevicesAndUsers' { @@ -45,6 +44,7 @@ function Set-CIPPAssignedPolicy { } } ) + break } default { Write-Host "We're supposed to assign a custom group. The group is $GroupName" @@ -53,22 +53,44 @@ function Set-CIPPAssignedPolicy { $Group = $_ foreach ($SingleName in $GroupNames) { if ($_.displayName -like $SingleName) { - $group.id + $_.id } } } - foreach ($Group in $GroupIds) { + $GroupIds | ForEach-Object { @{ target = @{ '@odata.type' = '#microsoft.graph.groupAssignmentTarget' - groupId = $Group + groupId = $_ } } } } } + + # Handle excludeGroup + if ($excludeGroup) { + $ExcludeGroupNames = $excludeGroup.Split(',') + $ExcludeGroupIds = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/groups?$select=id,displayName&$top=999' -tenantid $TenantFilter | ForEach-Object { + $Group = $_ + foreach ($SingleName in $ExcludeGroupNames) { + if ($_.displayName -like $SingleName) { + $_.id + } + } + } + $ExcludeGroupIds | ForEach-Object { + $assignmentsObject += @{ + target = @{ + '@odata.type' = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = $_ + } + } + } + } + $assignmentsObject = [PSCustomObject]@{ - assignments = @($assignmentsObject) + assignments = $assignmentsObject } $AssignJSON = ($assignmentsObject | ConvertTo-Json -Depth 10 -Compress) @@ -76,7 +98,7 @@ function Set-CIPPAssignedPolicy { if ($PSCmdlet.ShouldProcess($GroupName, "Assigning policy $PolicyId")) { Write-Host "https://graph.microsoft.com/beta/$($PlatformType)/$Type('$($PolicyId)')/assign" $null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$($PlatformType)/$Type('$($PolicyId)')/assign" -tenantid $tenantFilter -type POST -body $AssignJSON - Write-LogMessage -headers $Headers -API $APIName -message "Assigned $GroupName to Policy $PolicyId" -Sev 'Info' -tenant $TenantFilter + Write-LogMessage -headers $Headers -API $APIName -message "Assigned $GroupName and excluded $excludeGroup to Policy $PolicyId" -Sev 'Info' -tenant $TenantFilter } } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1 b/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1 index 85323c33a79d..64c51dfd5db5 100644 --- a/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1 @@ -6,6 +6,7 @@ function Set-CIPPIntunePolicy { $DisplayName, $RawJSON, $AssignTo, + $excludeGroup, $Headers, $APINAME, $tenantFilter @@ -135,7 +136,7 @@ function Set-CIPPIntunePolicy { Write-Host "Assigning policy to $($AssignTo) with ID $($CreateRequest.id) and type $TemplateTypeURL for tenant $tenantFilter" Write-Host "ID is $($CreateRequest.id)" - Set-CIPPAssignedPolicy -GroupName $AssignTo -PolicyId $CreateRequest.id -Type $TemplateTypeURL -TenantFilter $tenantFilter + Set-CIPPAssignedPolicy -GroupName $AssignTo -PolicyId $CreateRequest.id -Type $TemplateTypeURL -TenantFilter $tenantFilter -excludeGroup $excludeGroup } return "Successfully $($PostType) policy for $($tenantFilter) with display name $($Displayname)" } catch { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 index 68a437bd4bc4..7b61b1574aea 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 @@ -46,7 +46,7 @@ function Invoke-CIPPStandardIntuneTemplate { $description = $request.body.Description $RawJSON = $Request.body.RawJSON $Template.customGroup ? ($Template.AssignTo = $Template.customGroup) : $null - Set-CIPPIntunePolicy -TemplateType $Request.body.Type -Description $description -DisplayName $displayname -RawJSON $RawJSON -AssignTo $Template.AssignTo -tenantFilter $Tenant + Set-CIPPIntunePolicy -TemplateType $Request.body.Type -Description $description -DisplayName $displayname -RawJSON $RawJSON -AssignTo $Template.AssignTo -excludeGroup $Template.excludeGroup -tenantFilter $Tenant } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message From abfd08127d3675077923518bb21686e4867ab4c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Thu, 20 Feb 2025 22:25:15 +0100 Subject: [PATCH 034/167] Modernizations and support POST --- .../Entrypoints/Invoke-ExecUserSettings.ps1 | 3 ++- .../Entrypoints/Invoke-ListAppStatus.ps1 | 7 ++--- .../Entrypoints/Invoke-ListBreachesTenant.ps1 | 8 ++++-- .../Public/Entrypoints/Invoke-ListCSPsku.ps1 | 5 ++-- .../Entrypoints/Invoke-ListDeviceDetails.ps1 | 18 ++++++------- .../Public/Invoke-RemoveBPATemplate.ps1 | 24 +++++++++-------- .../Public/Invoke-RemoveCATemplate.ps1 | 24 +++++++++-------- .../Invoke-RemoveExConnectorTemplate.ps1 | 20 +++++++------- .../Public/Invoke-RemoveGroupTemplate.ps1 | 26 ++++++++++--------- .../Public/Invoke-RemoveIntuneTemplate.ps1 | 24 +++++++++-------- 10 files changed, 85 insertions(+), 74 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUserSettings.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUserSettings.ps1 index 82d1cb25041a..ee1b63556b4d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUserSettings.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUserSettings.ps1 @@ -10,7 +10,8 @@ function Invoke-ExecUserSettings { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' try { $object = $request.body.currentSettings | Select-Object * -ExcludeProperty CurrentTenant, pageSizes, sidebarShow, sidebarUnfoldable, _persist | ConvertTo-Json -Compress -Depth 10 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAppStatus.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAppStatus.ps1 index 10e0590e24c1..baac00b5b28a 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAppStatus.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAppStatus.ps1 @@ -14,18 +14,15 @@ Function Invoke-ListAppStatus { Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - # Interact with query parameters or the body of the request. - $tenantfilter = $Request.Query.TenantFilter + $TenantFilter = $Request.Query.TenantFilter $appFilter = $Request.Query.AppFilter Write-Host "Using $appFilter" $body = @" {"select":["DeviceName","UserPrincipalName","Platform","AppVersion","InstallState","InstallStateDetail","LastModifiedDateTime","DeviceId","ErrorCode","UserName","UserId","ApplicationId","AssignmentFilterIdsList","AppInstallState","AppInstallStateDetails","HexErrorCode"],"skip":0,"top":999,"filter":"(ApplicationId eq '$Appfilter')","orderBy":[]} "@ try { - $GraphRequest = New-Graphpostrequest -uri 'https://graph.microsoft.com/beta/deviceManagement/reports/getDeviceInstallStatusReport' -tenantid $TenantFilter -body $body + $GraphRequest = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/reports/getDeviceInstallStatusReport' -tenantid $TenantFilter -body $body $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListBreachesTenant.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListBreachesTenant.ps1 index 812a8c46b272..5e6104b3fdf3 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListBreachesTenant.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListBreachesTenant.ps1 @@ -10,7 +10,11 @@ Function Invoke-ListBreachesTenant { [CmdletBinding()] param($Request, $TriggerMetadata) - $TenantFilter = $Request.query.TenantFilter + $APIName = $Request.Params.CIPPEndpoint + Write-LogMessage -headers $Request.Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + $TenantFilter = $Request.query.tenantFilter + $Table = Get-CIPPTable -TableName UserBreaches if ($TenantFilter -ne 'AllTenants') { $filter = "PartitionKey eq '$TenantFilter'" @@ -22,7 +26,7 @@ Function Invoke-ListBreachesTenant { } catch { $usersResults = $null } - if ($usersResults -eq $null) { + if ($null -eq $usersResults) { $usersResults = @() } # Associate values to output bindings by calling 'Push-OutputBinding'. diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCSPsku.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCSPsku.ps1 index 4782121321b5..6753e0053477 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCSPsku.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCSPsku.ps1 @@ -12,11 +12,12 @@ Function Invoke-ListCSPsku { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $TenantFilter = $Request.Query.tenantFilter if ($Request.Query.currentSkuOnly) { - $GraphRequest = Get-SherwebCurrentSubscription -TenantFilter $Request.Query.TenantFilter + $GraphRequest = Get-SherwebCurrentSubscription -TenantFilter $TenantFilter } else { - $GraphRequest = Get-SherwebCatalog -TenantFilter $Request.Query.TenantFilter + $GraphRequest = Get-SherwebCatalog -TenantFilter $TenantFilter } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDeviceDetails.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDeviceDetails.ps1 index 2e1aa667bd40..83dfbdaf9002 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDeviceDetails.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDeviceDetails.ps1 @@ -13,36 +13,34 @@ Function Invoke-ListDeviceDetails { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + # XXX Seems to be an unused endpoint? -Bobby # Interact with query parameters or the body of the request. - $TenantFilter = $Request.Query.TenantFilter + $TenantFilter = $Request.Query.tenantFilter $DeviceID = $Request.Query.DeviceID $DeviceName = $Request.Query.DeviceName $DeviceSerial = $Request.Query.DeviceSerial try { if ($DeviceID) { - $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/managedDevices/$DeviceID" -Tenantid $tenantfilter + $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/managedDevices/$DeviceID" -Tenantid $TenantFilter } elseif ($DeviceSerial -or $DeviceName) { $Found = $False - if ($SeriaNumber -and $DeviceName) { - $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/managedDevices?`$filter=serialnumber eq '$DeviceSerial' and deviceName eq '$DeviceName'" -Tenantid $tenantfilter + if ($DeviceSerial -and $DeviceName) { + $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/managedDevices?`$filter=serialnumber eq '$DeviceSerial' and deviceName eq '$DeviceName'" -Tenantid $TenantFilter if (($GraphRequest | Measure-Object).count -eq 1 -and $GraphRequest.'@odata.count' -ne 0 ) { $Found = $True } } if ($DeviceSerial -and $Found -eq $False) { - $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/managedDevices?`$filter=serialnumber eq '$DeviceSerial'" -Tenantid $tenantfilter + $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/managedDevices?`$filter=serialnumber eq '$DeviceSerial'" -Tenantid $TenantFilter if (($GraphRequest | Measure-Object).count -eq 1 -and $GraphRequest.'@odata.count' -ne 0 ) { $Found = $True } } if ($DeviceName -and $Found -eq $False) { - $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/managedDevices?`$filter=deviceName eq '$DeviceName'" -Tenantid $tenantfilter + $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/managedDevices?`$filter=deviceName eq '$DeviceName'" -Tenantid $TenantFilter if (($GraphRequest | Measure-Object).count -eq 1 -and $GraphRequest.'@odata.count' -ne 0 ) { $Found = $True } @@ -80,7 +78,7 @@ Function Invoke-ListDeviceDetails { $DetectedApps = Get-GraphBulkResultByID -Results $BulkResults -ID 'DetectedApps' $Null = $GraphRequest | Add-Member -NotePropertyName 'DetectedApps' -NotePropertyValue ($DetectedApps.DetectedApps | Select-Object id, displayName, version) - $Null = $GraphRequest | Add-Member -NotePropertyName 'CompliancePolicies' -NotePropertyValue ($CompliancePolicies | Select-Object id, displayname, UserPrincipalName, state) + $Null = $GraphRequest | Add-Member -NotePropertyName 'CompliancePolicies' -NotePropertyValue ($CompliancePolicies | Select-Object id, displayName, UserPrincipalName, state) $Null = $GraphRequest | Add-Member -NotePropertyName 'DeviceGroups' -NotePropertyValue ($DeviceGroups | Select-Object id, displayName, description) diff --git a/Modules/CIPPCore/Public/Invoke-RemoveBPATemplate.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveBPATemplate.ps1 index 376e2a02918e..9282d94a4e30 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveBPATemplate.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveBPATemplate.ps1 @@ -11,29 +11,31 @@ Function Invoke-RemoveBPATemplate { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $User = $Request.Headers - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -Headers $Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - $ID = $request.query.TemplateName + $ID = $request.Query.TemplateName ?? $request.Body.TemplateName try { $Table = Get-CippTable -tablename 'templates' - $Filter = "PartitionKey eq 'BPATemplate' and RowKey eq '$id'" + $Filter = "PartitionKey eq 'BPATemplate' and RowKey eq '$ID'" $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey - Remove-AzDataTableEntity -Force @Table -Entity $clearRow - Write-LogMessage -Headers $User -API $APINAME -message "Removed BPA Template with ID $ID." -Sev 'Info' - $body = [pscustomobject]@{'Results' = 'Successfully removed BPA Template' } + Remove-AzDataTableEntity -Force @Table -Entity $ClearRow + $Result = "Removed BPA Template with ID $ID" + Write-LogMessage -Headers $Headers -API $APINAME -message $Result -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -message "Failed to remove BPA template $ID. $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage - $body = [pscustomobject]@{'Results' = "Failed to remove template: $($ErrorMessage.NormalizedError)" } + $Result = "Failed to remove BPA template with ID $ID. $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Headers -API $APINAME -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body + StatusCode = $StatusCode + Body = @{'Results' = $Result } }) diff --git a/Modules/CIPPCore/Public/Invoke-RemoveCATemplate.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveCATemplate.ps1 index d355cf2a2235..e800d423fc90 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveCATemplate.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveCATemplate.ps1 @@ -11,29 +11,31 @@ Function Invoke-RemoveCATemplate { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $User = $Request.Headers - $ID = $request.query.id - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + $ID = $request.Query.ID ?? $Request.Body.ID + Write-LogMessage -Headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' try { $Table = Get-CippTable -tablename 'templates' - $Filter = "PartitionKey eq 'CATemplate' and RowKey eq '$id'" + $Filter = "PartitionKey eq 'CATemplate' and RowKey eq '$ID'" $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey - Remove-AzDataTableEntity -Force @Table -Entity $clearRow - Write-LogMessage -Headers $User -API $APINAME -message "Removed Conditional Access Template with ID $ID." -Sev 'Info' - $body = [pscustomobject]@{'Results' = 'Successfully removed Conditional Access Template' } + Remove-AzDataTableEntity -Force @Table -Entity $ClearRow + $Result = "Removed Conditional Access Template with ID $ID" + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -message "Failed to remove Conditional Access template $ID. $($ErrorMessage.NormalizedError)" -Sev 'Error' - $body = [pscustomobject]@{'Results' = "Failed to remove template: $($ErrorMessage.NormalizedError)" } + $Result = "Failed to remove Conditional Access template $($ID): $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body + StatusCode = $StatusCode + Body = @{'Results' = $Result } }) diff --git a/Modules/CIPPCore/Public/Invoke-RemoveExConnectorTemplate.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveExConnectorTemplate.ps1 index 72eb798e3930..9a0174ca718e 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveExConnectorTemplate.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveExConnectorTemplate.ps1 @@ -11,28 +11,30 @@ Function Invoke-RemoveExConnectorTemplate { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $User = $Request.Headers - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -Headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' $ID = $Request.Query.ID ?? $Request.Body.ID try { $Table = Get-CippTable -tablename 'templates' $Filter = "PartitionKey eq 'ExConnectorTemplate' and RowKey eq '$ID'" $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey - Remove-AzDataTableEntity -Force @Table -Entity $clearRow - Write-LogMessage -Headers $User -API $APINAME -message "Removed Exchange Connector Template with ID $ID." -Sev 'Info' - $body = [pscustomobject]@{'Results' = 'Successfully removed Exchange Connector Template' } + Remove-AzDataTableEntity -Force @Table -Entity $ClearRow + $Result = "Removed Exchange Connector Template with ID $ID." + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -message "Failed to remove Exchange Connector Template $ID. $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage - $body = [pscustomobject]@{'Results' = "Failed to remove template: $($ErrorMessage.NormalizedError)" } + $Result = "Failed to remove Exchange Connector Template $($ID): $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body + StatusCode = $StatusCode + Body = @{'Results' = $Result } }) diff --git a/Modules/CIPPCore/Public/Invoke-RemoveGroupTemplate.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveGroupTemplate.ps1 index bf0c45d1f90d..a639ce683b81 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveGroupTemplate.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveGroupTemplate.ps1 @@ -11,31 +11,33 @@ Function Invoke-RemoveGroupTemplate { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $User = $Request.Headers - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -Headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - $ID = $request.query.id + $ID = $request.Query.ID ?? $Request.Body.ID try { $Table = Get-CippTable -tablename 'templates' - Write-Host $id + Write-Host $ID - $Filter = "PartitionKey eq 'GroupTemplate' and RowKey eq '$id'" + $Filter = "PartitionKey eq 'GroupTemplate' and RowKey eq '$ID'" Write-Host $Filter $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey - Remove-AzDataTableEntity -Force @Table -Entity $clearRow - Write-LogMessage -Headers $User -API $APINAME -message "Removed Intune Template with ID $ID." -Sev 'Info' - $body = [pscustomobject]@{'Results' = 'Successfully removed Template' } + Remove-AzDataTableEntity -Force @Table -Entity $ClearRow + $Result = "Removed Group Template with ID $ID" + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -message "Failed to remove intune template $ID. $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage - $body = [pscustomobject]@{'Results' = "Failed to remove template: $($ErrorMessage.NormalizedError)" } + $Result = "Failed to remove group template $($ID): $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body + StatusCode = $StatusCode + Body = @{'Results' = $Result } }) diff --git a/Modules/CIPPCore/Public/Invoke-RemoveIntuneTemplate.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveIntuneTemplate.ps1 index 636cf3fe7cfc..ab5fc1a85cb2 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveIntuneTemplate.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveIntuneTemplate.ps1 @@ -11,30 +11,32 @@ Function Invoke-RemoveIntuneTemplate { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $User = $Request.Headers - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -Headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - $ID = $request.query.id + $ID = $request.Query.ID ?? $Request.Body.ID try { $Table = Get-CippTable -tablename 'templates' - Write-Host $id + Write-Host $ID - $Filter = "PartitionKey eq 'IntuneTemplate' and RowKey eq '$id'" + $Filter = "PartitionKey eq 'IntuneTemplate' and RowKey eq '$ID'" Write-Host $Filter $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey Remove-AzDataTableEntity -Force @Table -Entity $clearRow - Write-LogMessage -Headers $User -API $APINAME -message "Removed Intune Template with ID $ID." -Sev 'Info' - $body = [pscustomobject]@{'Results' = 'Successfully removed Intune Template' } + $Result = "Removed Intune Template with ID $ID" + Write-LogMessage -Headers $Headers -API $APINAME -message $Result -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -message "Failed to remove intune template $ID. $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage - $body = [pscustomobject]@{'Results' = "Failed to remove template: $($ErrorMessage.NormalizedError)" } + $Result = "Failed to remove Intune template $($ID): $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Headers -API $APINAME -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body + StatusCode = $StatusCode + Body = @{'Results' = $Result } }) From 6c2ff6fda975c2200e08c3f5b270799629004d7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Thu, 20 Feb 2025 22:27:48 +0100 Subject: [PATCH 035/167] Remove unused comment --- .../CIPPCore/Public/Entrypoints/Invoke-ListPendingWebhooks.ps1 | 2 -- 1 file changed, 2 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPendingWebhooks.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPendingWebhooks.ps1 index ddad3aa638a7..e344ac10776e 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPendingWebhooks.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPendingWebhooks.ps1 @@ -13,8 +13,6 @@ Function Invoke-ListPendingWebhooks { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' try { $Table = Get-CIPPTable -TableName 'WebhookIncoming' $Webhooks = Get-CIPPAzDataTableEntity @Table From b513b19aec01603d6209f4bc0136f2aaf0af75fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Fri, 21 Feb 2025 16:11:09 +0100 Subject: [PATCH 036/167] Add listType property manually to make deletion possible without too much hassle --- .../Invoke-ListTenantAllowBlockList.ps1 | 23 ++++++++----------- .../Invoke-RemoveTenantAllowBlockList.ps1 | 10 +++----- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListTenantAllowBlockList.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListTenantAllowBlockList.ps1 index 01dcabaf6174..aa5ae37c50dc 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListTenantAllowBlockList.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListTenantAllowBlockList.ps1 @@ -13,32 +13,27 @@ Function Invoke-ListTenantAllowBlockList { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - # Interact with query parameters or the body of the request. $TenantFilter = $Request.Query.TenantFilter $ListTypes = 'Sender', 'Url', 'FileHash' try { - $cmdletArray = $ListTypes | ForEach-Object { - @{ - CmdletInput = @{ - CmdletName = 'Get-TenantAllowBlockListItems' - Parameters = @{ListType = $_ } - } - } - } - $BatchResults = New-ExoBulkRequest -tenantid $TenantFilter -cmdletArray @($cmdletArray) + $Results = $ListTypes | ForEach-Object -Parallel { + Import-Module '.\Modules\AzBobbyTables' + Import-Module '.\Modules\CIPPCore' + $TempResults = New-ExoRequest -tenantid $using:TenantFilter -cmdlet 'Get-TenantAllowBlockListItems' -cmdParams @{ListType = $_ } + $TempResults | Add-Member -MemberType NoteProperty -Name ListType -Value $_ + $TempResults | Select-Object -ExcludeProperty *'@data.type'*, *'(DateTime])'* + } -ThrottleLimit 5 $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message $StatusCode = [HttpStatusCode]::Forbidden - $BatchResults = $ErrorMessage + $Results = $ErrorMessage } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = $StatusCode - Body = @($BatchResults) + Body = @($Results) }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1 index c02775315ee9..1747067a57a9 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1 @@ -16,15 +16,11 @@ Function Invoke-RemoveTenantAllowBlockList { Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' # Interact with query parameters or the body of the request. - $Entries = $Request.Body.entries + $Entries = $Request.Body.Entries + $ListType = $Request.Body.ListType try { - $listType = switch -Wildcard ($Entries) { - '*@*' { 'Sender'; break } - '*.*' { 'Url'; break } - default { 'FileHash' } - } Write-Host "List type is $listType" $ExoRequest = @{ tenantid = $TenantFilter @@ -53,7 +49,7 @@ Function Invoke-RemoveTenantAllowBlockList { StatusCode = $StatusCode Body = @{ 'Results' = $Result - 'Request' = $ExoRequest + # 'Request' = $ExoRequest } }) } From 0df20093ac98be7705939e58af3ca4906c0ecbc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Fri, 21 Feb 2025 16:14:54 +0100 Subject: [PATCH 037/167] Better logging message --- .../Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1 index 1747067a57a9..70b4d553949b 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1 @@ -34,12 +34,12 @@ Function Invoke-RemoveTenantAllowBlockList { $Results = New-ExoRequest @ExoRequest Write-Host $Results - $Result = "Successfully removed $($Entries) from Block/Allow list" + $Result = "Successfully removed $($Entries) with type $ListType from Block/Allow list" Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Info' $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - $Result = "Failed to remove $($Entries). Error: $($ErrorMessage.NormalizedError)" + $Result = "Failed to remove $($Entries) type $ListType. Error: $($ErrorMessage.NormalizedError)" Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage $StatusCode = [HttpStatusCode]::Forbidden } From 71b7002fb0f8b4bff79d1a48381d3555633be616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Fri, 21 Feb 2025 16:18:04 +0100 Subject: [PATCH 038/167] Dont import stuff that isnt needed --- .../Public/Entrypoints/Invoke-ListTenantAllowBlockList.ps1 | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListTenantAllowBlockList.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListTenantAllowBlockList.ps1 index aa5ae37c50dc..84c536889682 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListTenantAllowBlockList.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListTenantAllowBlockList.ps1 @@ -14,12 +14,11 @@ Function Invoke-ListTenantAllowBlockList { Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' # Interact with query parameters or the body of the request. - $TenantFilter = $Request.Query.TenantFilter + $TenantFilter = $Request.Query.tenantFilter $ListTypes = 'Sender', 'Url', 'FileHash' try { $Results = $ListTypes | ForEach-Object -Parallel { - Import-Module '.\Modules\AzBobbyTables' - Import-Module '.\Modules\CIPPCore' + Import-Module CIPPCore $TempResults = New-ExoRequest -tenantid $using:TenantFilter -cmdlet 'Get-TenantAllowBlockListItems' -cmdParams @{ListType = $_ } $TempResults | Add-Member -MemberType NoteProperty -Name ListType -Value $_ $TempResults | Select-Object -ExcludeProperty *'@data.type'*, *'(DateTime])'* From 4e3524ca724b889ea40aaee89bc0991fffe42696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Fri, 21 Feb 2025 17:09:42 +0100 Subject: [PATCH 039/167] add forgotten logging --- .../Endpoint/MEM/Invoke-RemoveIntuneScript.ps1 | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-RemoveIntuneScript.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-RemoveIntuneScript.ps1 index 4770fbe1638a..d88f03a9f998 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-RemoveIntuneScript.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-RemoveIntuneScript.ps1 @@ -14,12 +14,11 @@ function Invoke-RemoveIntuneScript { $Headers = $Request.Headers Write-LogMessage -Headers $Headers -API $APINAME -message 'Accessed this API' -Sev Debug - Write-Host 'PowerShell HTTP trigger function processed a request.' - - $TenantFilter = $Request.body.TenantFilter - $ID = $Request.body.ID - $ScriptType = $Request.body.ScriptType - $DisplayName = $Request.body.DisplayName + # Interact with query parameters or the body of the request. + $TenantFilter = $Request.Body.TenantFilter + $ID = $Request.Body.ID + $ScriptType = $Request.Body.ScriptType + $DisplayName = $Request.Body.DisplayName try { @@ -41,10 +40,12 @@ function Invoke-RemoveIntuneScript { $null = New-GraphPOSTRequest -uri $URI -type DELETE -tenantid $TenantFilter $Result = "Deleted $($ScriptType) script $($DisplayName) with ID: $($ID)" + Write-LogMessage -headers $.Headers -API $APINAME -tenant $Tenant -message $Result -Sev 'Info' $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ $Result = "Failed to delete $($ScriptType) script $($DisplayName). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APINAME -tenant $Tenant -message $Result -Sev 'Error' $StatusCode = [HttpStatusCode]::Forbidden } From b1e77ca68c54a429934068ea15b00b46c2811264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Fri, 21 Feb 2025 17:13:11 +0100 Subject: [PATCH 040/167] Modernize more endpoints --- .../Invoke-ListTransportRules.ps1 | 6 +++--- .../Reports/Invoke-ListAntiPhishingFilters.ps1 | 16 +++++++--------- .../Reports/Invoke-ListGlobalAddressList.ps1 | 3 ++- .../Reports/Invoke-ListMalwareFilters.ps1 | 17 +++++++---------- .../Invoke-ListSafeAttachmentsFilters.ps1 | 17 +++++++---------- .../Reports/Invoke-ListSafeLinksFilters.ps1 | 17 +++++++---------- .../Invoke-ListTeamsLisLocation.ps1 | 4 +++- .../Invoke-ListTenantOnboarding.ps1 | 12 ++++++++---- .../Tenant/GDAP/Invoke-ListGDAPInvite.ps1 | 8 ++++---- .../Tenant/GDAP/Invoke-ListGDAPQueue.ps1 | 3 +-- .../Entrypoints/Invoke-ListServiceHealth.ps1 | 16 ++++++++-------- .../Invoke-ListSharedMailboxStatistics.ps1 | 4 +--- 12 files changed, 58 insertions(+), 65 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListTransportRules.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListTransportRules.ps1 index 702247ac6b3e..aeb9f976be35 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListTransportRules.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListTransportRules.ps1 @@ -11,11 +11,11 @@ Function Invoke-ListTransportRules { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - $Tenantfilter = $request.Query.tenantfilter + Write-LogMessage -headers $Request.Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $TenantFilter = $request.Query.tenantFilter try { - $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet 'Get-TransportRule' + $GraphRequest = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-TransportRule' $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListAntiPhishingFilters.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListAntiPhishingFilters.ps1 index 2f2d87e830b9..d303554b1358 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListAntiPhishingFilters.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListAntiPhishingFilters.ps1 @@ -11,23 +11,21 @@ function Invoke-ListAntiPhishingFilters { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' # Interact with query parameters or the body of the request. $TenantFilter = $Request.Query.TenantFilter - $Policys = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-AntiPhishPolicy' | Select-Object -Property * + $Policies = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-AntiPhishPolicy' | Select-Object -Property * $Rules = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-AntiPhishRule' | Select-Object -Property * - $Output = $Policys | Select-Object -Property *, - @{ Name = 'RuleName'; Expression = { foreach ($item in $Rules) { if ($item.AntiPhishPolicy -eq $_.Name) { $item.Name } } } }, - @{ Name = 'Priority'; Expression = { foreach ($item in $Rules) { if ($item.AntiPhishPolicy -eq $_.Name) { $item.Priority } } } }, - @{ Name = 'RecipientDomainIs'; Expression = { foreach ($item in $Rules) { if ($item.AntiPhishPolicy -eq $_.Name) { $item.RecipientDomainIs } } } }, - @{ Name = 'State'; Expression = { foreach ($item in $Rules) { if ($item.AntiPhishPolicy -eq $_.Name) { $item.State } } } } + $Output = $Policies | Select-Object -Property *, + @{ Name = 'RuleName'; Expression = { foreach ($item in $Rules) { if ($item.AntiPhishPolicy -eq $_.Name) { $item.Name } } } }, + @{ Name = 'Priority'; Expression = { foreach ($item in $Rules) { if ($item.AntiPhishPolicy -eq $_.Name) { $item.Priority } } } }, + @{ Name = 'RecipientDomainIs'; Expression = { foreach ($item in $Rules) { if ($item.AntiPhishPolicy -eq $_.Name) { $item.RecipientDomainIs } } } }, + @{ Name = 'State'; Expression = { foreach ($item in $Rules) { if ($item.AntiPhishPolicy -eq $_.Name) { $item.State } } } } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK Body = $Output - }) + }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListGlobalAddressList.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListGlobalAddressList.ps1 index 15d5702ce0a1..9067a2df0ac7 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListGlobalAddressList.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListGlobalAddressList.ps1 @@ -17,7 +17,8 @@ Function Invoke-ListGlobalAddressList { try { $GAL = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-Recipient' -cmdParams @{ResultSize = 'unlimited'; SortBy = 'DisplayName' } ` - -Select 'Identity, DisplayName, Alias, PrimarySmtpAddress, ExternalDirectoryObjectId, HiddenFromAddressListsEnabled, EmailAddresses, IsDirSynced, SKUAssigned, RecipientType, RecipientTypeDetails, AddressListMembership' | Select-Object -ExcludeProperty *odata*, *data.type* + -Select 'Identity, DisplayName, Alias, PrimarySmtpAddress, ExternalDirectoryObjectId, HiddenFromAddressListsEnabled, EmailAddresses, IsDirSynced, SKUAssigned, RecipientType, RecipientTypeDetails, AddressListMembership' | + Select-Object -ExcludeProperty *odata*, *data.type* $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMalwareFilters.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMalwareFilters.ps1 index ae91d9091d1d..d067881265cf 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMalwareFilters.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMalwareFilters.ps1 @@ -11,23 +11,20 @@ function Invoke-ListMalwareFilters { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - # Interact with query parameters or the body of the request. $TenantFilter = $Request.Query.TenantFilter - $Policys = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-MalwareFilterPolicy' | Select-Object -Property * + $Policies = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-MalwareFilterPolicy' | Select-Object -Property * $Rules = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-MalwareFilterRule' | Select-Object -Property * - $Output = $Policys | Select-Object -Property *, - @{ Name = 'RuleName'; Expression = { foreach ($item in $Rules) { if ($item.MalwareFilterPolicy -eq $_.Name) { $item.Name } } } }, - @{ Name = 'Priority'; Expression = { foreach ($item in $Rules) { if ($item.MalwareFilterPolicy -eq $_.Name) { $item.Priority } } } }, - @{ Name = 'RecipientDomainIs'; Expression = { foreach ($item in $Rules) { if ($item.MalwareFilterPolicy -eq $_.Name) { $item.RecipientDomainIs } } } }, - @{ Name = 'State'; Expression = { foreach ($item in $Rules) { if ($item.MalwareFilterPolicy -eq $_.Name) { $item.State } } } } + $Output = $Policies | Select-Object -Property *, + @{ Name = 'RuleName'; Expression = { foreach ($item in $Rules) { if ($item.MalwareFilterPolicy -eq $_.Name) { $item.Name } } } }, + @{ Name = 'Priority'; Expression = { foreach ($item in $Rules) { if ($item.MalwareFilterPolicy -eq $_.Name) { $item.Priority } } } }, + @{ Name = 'RecipientDomainIs'; Expression = { foreach ($item in $Rules) { if ($item.MalwareFilterPolicy -eq $_.Name) { $item.RecipientDomainIs } } } }, + @{ Name = 'State'; Expression = { foreach ($item in $Rules) { if ($item.MalwareFilterPolicy -eq $_.Name) { $item.State } } } } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK Body = $Output - }) + }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeAttachmentsFilters.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeAttachmentsFilters.ps1 index 1138b77c2642..cea8b9313937 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeAttachmentsFilters.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeAttachmentsFilters.ps1 @@ -11,23 +11,20 @@ function Invoke-ListSafeAttachmentsFilters { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - # Interact with query parameters or the body of the request. $TenantFilter = $Request.Query.TenantFilter - $Policys = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-SafeAttachmentPolicy' | Select-Object -Property * + $Policies = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-SafeAttachmentPolicy' | Select-Object -Property * $Rules = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-SafeAttachmentRule' | Select-Object -Property * - $Output = $Policys | Select-Object -Property *, - @{ Name = 'RuleName'; Expression = { foreach ($item in $Rules) { if ($item.SafeAttachmentPolicy -eq $_.Name) { $item.Name } } } }, - @{ Name = 'Priority'; Expression = { foreach ($item in $Rules) { if ($item.SafeAttachmentPolicy -eq $_.Name) { $item.Priority } } } }, - @{ Name = 'RecipientDomainIs'; Expression = { foreach ($item in $Rules) { if ($item.SafeAttachmentPolicy -eq $_.Name) { $item.RecipientDomainIs } } } }, - @{ Name = 'State'; Expression = { foreach ($item in $Rules) { if ($item.SafeAttachmentPolicy -eq $_.Name) { $item.State } } } } + $Output = $Policies | Select-Object -Property *, + @{ Name = 'RuleName'; Expression = { foreach ($item in $Rules) { if ($item.SafeAttachmentPolicy -eq $_.Name) { $item.Name } } } }, + @{ Name = 'Priority'; Expression = { foreach ($item in $Rules) { if ($item.SafeAttachmentPolicy -eq $_.Name) { $item.Priority } } } }, + @{ Name = 'RecipientDomainIs'; Expression = { foreach ($item in $Rules) { if ($item.SafeAttachmentPolicy -eq $_.Name) { $item.RecipientDomainIs } } } }, + @{ Name = 'State'; Expression = { foreach ($item in $Rules) { if ($item.SafeAttachmentPolicy -eq $_.Name) { $item.State } } } } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK Body = $Output - }) + }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeLinksFilters.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeLinksFilters.ps1 index 0b4c2d60788b..0c7ced24871a 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeLinksFilters.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeLinksFilters.ps1 @@ -11,23 +11,20 @@ function Invoke-ListSafeLinksFilters { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - # Interact with query parameters or the body of the request. $TenantFilter = $Request.Query.TenantFilter - $Policys = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-SafeLinksPolicy' | Select-Object -Property * + $Policies = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-SafeLinksPolicy' | Select-Object -Property * $Rules = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-SafeLinksRule' | Select-Object -Property * - $Output = $Policys | Select-Object -Property *, - @{ Name = 'RuleName'; Expression = { foreach ($item in $Rules) { if ($item.SafeLinksPolicy -eq $_.Name) { $item.Name } } } }, - @{ Name = 'Priority'; Expression = { foreach ($item in $Rules) { if ($item.SafeLinksPolicy -eq $_.Name) { $item.Priority } } } }, - @{ Name = 'RecipientDomainIs'; Expression = { foreach ($item in $Rules) { if ($item.SafeLinksPolicy -eq $_.Name) { $item.RecipientDomainIs } } } }, - @{ Name = 'State'; Expression = { foreach ($item in $Rules) { if ($item.SafeLinksPolicy -eq $_.Name) { $item.State } } } } + $Output = $Policies | Select-Object -Property *, + @{ Name = 'RuleName'; Expression = { foreach ($item in $Rules) { if ($item.SafeLinksPolicy -eq $_.Name) { $item.Name } } } }, + @{ Name = 'Priority'; Expression = { foreach ($item in $Rules) { if ($item.SafeLinksPolicy -eq $_.Name) { $item.Priority } } } }, + @{ Name = 'RecipientDomainIs'; Expression = { foreach ($item in $Rules) { if ($item.SafeLinksPolicy -eq $_.Name) { $item.RecipientDomainIs } } } }, + @{ Name = 'State'; Expression = { foreach ($item in $Rules) { if ($item.SafeLinksPolicy -eq $_.Name) { $item.State } } } } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK Body = $Output - }) + }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsLisLocation.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsLisLocation.ps1 index d8b0f95656dd..a801c93077b0 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsLisLocation.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsLisLocation.ps1 @@ -11,7 +11,9 @@ Function Invoke-ListTeamsLisLocation { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $TenantFilter = $Request.Query.TenantFilter try { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListTenantOnboarding.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListTenantOnboarding.ps1 index 8fee5dbf56f8..843248a2d2ff 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListTenantOnboarding.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListTenantOnboarding.ps1 @@ -5,10 +5,14 @@ function Invoke-ListTenantOnboarding { .ROLE Tenant.Administration.Read #> - Param( - $Request, - $TriggerMetadata - ) + Param($Request, $TriggerMetadata) + + + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + + try { $OnboardTable = Get-CIPPTable -TableName 'TenantOnboarding' $TenantOnboardings = Get-CIPPAzDataTableEntity @OnboardTable diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPInvite.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPInvite.ps1 index 62fbb532c26c..578a0cc2db93 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPInvite.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPInvite.ps1 @@ -14,12 +14,12 @@ Function Invoke-ListGDAPInvite { Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + # Interact with query parameters or the body of the request. + $RelationshipId = $Request.Query.RelationshipId $Table = Get-CIPPTable -TableName 'GDAPInvites' - if (![string]::IsNullOrEmpty($Request.Query.RelationshipId)) { - $Invite = Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq '$($Request.Query.RelationshipId)'" + if (![string]::IsNullOrEmpty($RelationshipId)) { + $Invite = Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq '$($RelationshipId)'" } else { $Invite = Get-CIPPAzDataTableEntity @Table | ForEach-Object { $_.RoleMappings = @(try { $_.RoleMappings | ConvertFrom-Json } catch { $_.RoleMappings }) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPQueue.ps1 index f99e814e04a8..cc2d40b78077 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPQueue.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPQueue.ps1 @@ -13,9 +13,8 @@ Function Invoke-ListGDAPQueue { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + # XXX Seems to be an unused endpoint? -Bobby - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' $Table = Get-CIPPTable -TableName 'GDAPMigration' $QueuedApps = Get-CIPPAzDataTableEntity @Table diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListServiceHealth.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListServiceHealth.ps1 index a7213fbf18b9..160533a5d1f9 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListServiceHealth.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListServiceHealth.ps1 @@ -10,12 +10,13 @@ Function Invoke-ListServiceHealth { [CmdletBinding()] param($Request, $TriggerMetadata) - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + $TenantFilter = $Request.Query.tenantFilter + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - if ($Request.query.tenantFilter -eq 'AllTenants') { + if ($TenantFilter -eq 'AllTenants') { $ResultHealthSummary = Get-Tenants | ForEach-Object -Parallel { Import-Module '.\Modules\AzBobbyTables' Import-Module '.\Modules\CIPPCore' @@ -27,10 +28,9 @@ Function Invoke-ListServiceHealth { $prop } } else { - $TenantName = $Request.query.displayName - $TenantID = $Request.query.tenantFilter - $DefaultDomainName = $Request.query.defaultDomainName - $ResultHealthSummary = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/admin/serviceAnnouncement/issues?`$filter=endDateTime eq null" -tenantid $TenantID + $TenantName = $Request.Query.displayName + $DefaultDomainName = $Request.Query.defaultDomainName + $ResultHealthSummary = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/admin/serviceAnnouncement/issues?`$filter=endDateTime eq null" -tenantid $TenantFilter $ResultHealthSummary | Add-Member -NotePropertyName 'tenant' -NotePropertyValue $TenantName $ResultHealthSummary | Add-Member -NotePropertyName 'defaultDomainName' -NotePropertyValue $DefaultDomainName Write-Host "Processed Service Health for $TenantName" diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxStatistics.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxStatistics.ps1 index 996e6f13dc53..96edbf15faeb 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxStatistics.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxStatistics.ps1 @@ -13,9 +13,7 @@ Function Invoke-ListSharedMailboxStatistics { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + # XXX Seems like an unused endpoint? -Bobby # Interact with query parameters or the body of the request. $TenantFilter = $Request.Query.TenantFilter From 096b65d19e4742e0e9864297a4cc6c7a135c40ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sat, 22 Feb 2025 11:51:00 +0100 Subject: [PATCH 041/167] Fix SP site admin permission changes --- .../Invoke-ExecSharePointPerms.ps1 | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSharePointPerms.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSharePointPerms.ps1 index 8f6e939440fb..e2c91f14a12e 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSharePointPerms.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSharePointPerms.ps1 @@ -16,32 +16,40 @@ Function Invoke-ExecSharePointPerms { Write-LogMessage -Headers $Headers -API $APIName -message 'Accessed this API' -Sev Debug + Write-Host '====================================' + Write-Host 'Request Body:' + Write-Host (ConvertTo-Json $Request.body -Depth 10) + Write-Host '====================================' + + # The UPN or ID of the users OneDrive we are changing permissions on - $UserId = $Request.body.UPN + $UserId = $Request.Body.UPN # The UPN of the user we are adding or removing permissions for - $OnedriveAccessUser = $Request.body.onedriveAccessUser.value + $OnedriveAccessUser = $Request.Body.onedriveAccessUser.value ?? $Request.Body.user.value + $URL = $Request.Body.URL + $RemovePermission = $Request.Body.RemovePermission try { $State = Set-CIPPSharePointPerms -tenantFilter $tenantFilter ` -UserId $UserId ` -OnedriveAccessUser $OnedriveAccessUser ` - -Headers $Request.Headers ` + -Headers $Headers ` -APIName $APIName ` - -RemovePermission $Request.body.RemovePermission ` - -URL $Request.Body.URL - $Results = [pscustomobject]@{'Results' = "$State" } + -RemovePermission $RemovePermission ` + -URL $URL + $Result = "$State" $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - $Results = [pscustomobject]@{'Results' = "Failed. $($ErrorMessage.NormalizedError)" } + $Result = "Failed. $($ErrorMessage.NormalizedError)" $StatusCode = [HttpStatusCode]::BadRequest } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = $StatusCode - Body = $Results + Body = @{'Results' = $Result } }) } From d55cd03122e1e071e727c7916804ca0cbebfc918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sat, 22 Feb 2025 12:25:01 +0100 Subject: [PATCH 042/167] Refactor API logging and parameter handling for consistency --- .../Administration/Users/Invoke-ListUsers.ps1 | 18 ++++---- .../Alerts/Invoke-ListAuditLogs.ps1 | 41 +++++++++++-------- .../Invoke-ListConditionalAccessPolicies.ps1 | 9 ++-- ...oke-ListConditionalAccessPolicyChanges.ps1 | 37 ++++++++--------- 4 files changed, 52 insertions(+), 53 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUsers.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUsers.ps1 index 0f6ff909234f..91dfb2187187 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUsers.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUsers.ps1 @@ -10,10 +10,9 @@ Function Invoke-ListUsers { [CmdletBinding()] param($Request, $TriggerMetadata) - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $APIName = $Request.Params.CIPPEndpoint + Write-LogMessage -headers $Request.Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' $ConvertTable = Import-Csv ConversionTable.csv | Sort-Object -Property 'guid' -Unique # Interact with query parameters or the body of the request. $TenantFilter = $Request.Query.TenantFilter @@ -38,11 +37,11 @@ Function Invoke-ListUsers { Message = 'This function has been deprecated for all users, please use ListGraphRequest instead' } } else { - $Rows.Data | ConvertFrom-Json | Select-Object $selectlist | ForEach-Object { + $Rows.Data | ConvertFrom-Json | Select-Object $SelectList | ForEach-Object { $_.onPremisesSyncEnabled = [bool]($_.onPremisesSyncEnabled) - $_.Aliases = $_.Proxyaddresses -join ', ' + $_.Aliases = $_.proxyAddresses -join ', ' $SkuID = $_.AssignedLicenses.skuid - $_.LicJoined = ($ConvertTable | Where-Object { $_.guid -in $skuid }).'Product_Display_Name' -join ', ' + $_.LicJoined = ($ConvertTable | Where-Object { $_.guid -in $SkuID }).'Product_Display_Name' -join ', ' $_.primDomain = @{value = ($_.userPrincipalName -split '@' | Select-Object -Last 1) } $_ } @@ -62,8 +61,9 @@ Function Invoke-ListUsers { endDate = $endDate UserIds = @($GraphRequest.userPrincipalName) } - $AuditlogsLogon = (New-ExoRequest -tenantid $Tenantfilter -cmdlet 'Search-unifiedAuditLog' -cmdParams $SearchParam | Sort-Object -Property CreationDate | Select-Object -Last 1).auditdata | ConvertFrom-Json - $Appname = '[{"Application Name":"ACOM Azure Website","Application IDs":"23523755-3a2b-41ca-9315-f81f3f566a95"},{"Application Name":"AEM-DualAuth","Application IDs":"69893ee3-dd10-4b1c-832d-4870354be3d8"},{"Application Name":"ASM Campaign Servicing","Application IDs":"0cb7b9ec-5336-483b-bc31-b15b5788de71"},{"Application Name":"Azure Advanced Threat Protection","Application IDs":"7b7531ad-5926-4f2d-8a1d-38495ad33e17"},{"Application Name":"Azure Data Lake","Application IDs":"e9f49c6b-5ce5-44c8-925d-015017e9f7ad"},{"Application Name":"Azure Lab Services Portal","Application IDs":"835b2a73-6e10-4aa5-a979-21dfda45231c"},{"Application Name":"Azure Portal","Application IDs":"c44b4083-3bb0-49c1-b47d-974e53cbdf3c"},{"Application Name":"AzureSupportCenter","Application IDs":"37182072-3c9c-4f6a-a4b3-b3f91cacffce"},{"Application Name":"Bing","Application IDs":"9ea1ad79-fdb6-4f9a-8bc3-2b70f96e34c7"},{"Application Name":"CPIM Service","Application IDs":"bb2a2e3a-c5e7-4f0a-88e0-8e01fd3fc1f4"},{"Application Name":"CRM Power BI Integration","Application IDs":"e64aa8bc-8eb4-40e2-898b-cf261a25954f"},{"Application Name":"Dataverse","Application IDs":"00000007-0000-0000-c000-000000000000"},{"Application Name":"Enterprise Roaming and Backup","Application IDs":"60c8bde5-3167-4f92-8fdb-059f6176dc0f"},{"Application Name":"IAM Supportability","Application IDs":"a57aca87-cbc0-4f3c-8b9e-dc095fdc8978"},{"Application Name":"IrisSelectionFrontDoor","Application IDs":"16aeb910-ce68-41d1-9ac3-9e1673ac9575"},{"Application Name":"MCAPI Authorization Prod","Application IDs":"d73f4b35-55c9-48c7-8b10-651f6f2acb2e"},{"Application Name":"Media Analysis and Transformation Service","Application IDs":"944f0bd1-117b-4b1c-af26-804ed95e767e
0cd196ee-71bf-4fd6-a57c-b491ffd4fb1e"},{"Application Name":"Microsoft 365 Support Service","Application IDs":"ee272b19-4411-433f-8f28-5c13cb6fd407"},{"Application Name":"Microsoft App Access Panel","Application IDs":"0000000c-0000-0000-c000-000000000000"},{"Application Name":"Microsoft Approval Management","Application IDs":"65d91a3d-ab74-42e6-8a2f-0add61688c74
38049638-cc2c-4cde-abe4-4479d721ed44"},{"Application Name":"Microsoft Authentication Broker","Application IDs":"29d9ed98-a469-4536-ade2-f981bc1d605e"},{"Application Name":"Microsoft Azure CLI","Application IDs":"04b07795-8ddb-461a-bbee-02f9e1bf7b46"},{"Application Name":"Microsoft Azure PowerShell","Application IDs":"1950a258-227b-4e31-a9cf-717495945fc2"},{"Application Name":"Microsoft Bing Search","Application IDs":"cf36b471-5b44-428c-9ce7-313bf84528de"},{"Application Name":"Microsoft Bing Search for Microsoft Edge","Application IDs":"2d7f3606-b07d-41d1-b9d2-0d0c9296a6e8"},{"Application Name":"Microsoft Bing Default Search Engine","Application IDs":"1786c5ed-9644-47b2-8aa0-7201292175b6"},{"Application Name":"Microsoft Defender for Cloud Apps","Application IDs":"3090ab82-f1c1-4cdf-af2c-5d7a6f3e2cc7"},{"Application Name":"Microsoft Docs","Application IDs":"18fbca16-2224-45f6-85b0-f7bf2b39b3f3"},{"Application Name":"Microsoft Dynamics ERP","Application IDs":"00000015-0000-0000-c000-000000000000"},{"Application Name":"Microsoft Edge Insider Addons Prod","Application IDs":"6253bca8-faf2-4587-8f2f-b056d80998a7"},{"Application Name":"Microsoft Exchange Online Protection","Application IDs":"00000007-0000-0ff1-ce00-000000000000"},{"Application Name":"Microsoft Forms","Application IDs":"c9a559d2-7aab-4f13-a6ed-e7e9c52aec87"},{"Application Name":"Microsoft Graph","Application IDs":"00000003-0000-0000-c000-000000000000"},{"Application Name":"Microsoft Intune Web Company Portal","Application IDs":"74bcdadc-2fdc-4bb3-8459-76d06952a0e9"},{"Application Name":"Microsoft Intune Windows Agent","Application IDs":"fc0f3af4-6835-4174-b806-f7db311fd2f3"},{"Application Name":"Microsoft Learn","Application IDs":"18fbca16-2224-45f6-85b0-f7bf2b39b3f3"},{"Application Name":"Microsoft Office","Application IDs":"d3590ed6-52b3-4102-aeff-aad2292ab01c"},{"Application Name":"Microsoft Office 365 Portal","Application IDs":"00000006-0000-0ff1-ce00-000000000000"},{"Application Name":"Microsoft Office Web Apps Service","Application IDs":"67e3df25-268a-4324-a550-0de1c7f97287"},{"Application Name":"Microsoft Online Syndication Partner Portal","Application IDs":"d176f6e7-38e5-40c9-8a78-3998aab820e7"},{"Application Name":"Microsoft password reset service","Application IDs":"93625bc8-bfe2-437a-97e0-3d0060024faa"},{"Application Name":"Microsoft Power BI","Application IDs":"871c010f-5e61-4fb1-83ac-98610a7e9110"},{"Application Name":"Microsoft Storefronts","Application IDs":"28b567f6-162c-4f54-99a0-6887f387bbcc"},{"Application Name":"Microsoft Stream Portal","Application IDs":"cf53fce8-def6-4aeb-8d30-b158e7b1cf83"},{"Application Name":"Microsoft Substrate Management","Application IDs":"98db8bd6-0cc0-4e67-9de5-f187f1cd1b41"},{"Application Name":"Microsoft Support","Application IDs":"fdf9885b-dd37-42bf-82e5-c3129ef5a302"},{"Application Name":"Microsoft Teams","Application IDs":"1fec8e78-bce4-4aaf-ab1b-5451cc387264"},{"Application Name":"Microsoft Teams Services","Application IDs":"cc15fd57-2c6c-4117-a88c-83b1d56b4bbe"},{"Application Name":"Microsoft Teams Web Client","Application IDs":"5e3ce6c0-2b1f-4285-8d4b-75ee78787346"},{"Application Name":"Microsoft Whiteboard Services","Application IDs":"95de633a-083e-42f5-b444-a4295d8e9314"},{"Application Name":"O365 Suite UX","Application IDs":"4345a7b9-9a63-4910-a426-35363201d503"},{"Application Name":"Office 365 Exchange Online","Application IDs":"00000002-0000-0ff1-ce00-000000000000"},{"Application Name":"Office 365 Management","Application IDs":"00b41c95-dab0-4487-9791-b9d2c32c80f2"},{"Application Name":"Office 365 Search Service","Application IDs":"66a88757-258c-4c72-893c-3e8bed4d6899"},{"Application Name":"Office 365 SharePoint Online","Application IDs":"00000003-0000-0ff1-ce00-000000000000"},{"Application Name":"Office Delve","Application IDs":"94c63fef-13a3-47bc-8074-75af8c65887a"},{"Application Name":"Office Online Add-in SSO","Application IDs":"93d53678-613d-4013-afc1-62e9e444a0a5"},{"Application Name":"Office Online Client AAD- Augmentation Loop","Application IDs":"2abdc806-e091-4495-9b10-b04d93c3f040"},{"Application Name":"Office Online Client AAD- Loki","Application IDs":"b23dd4db-9142-4734-867f-3577f640ad0c"},{"Application Name":"Office Online Client AAD- Maker","Application IDs":"17d5e35f-655b-4fb0-8ae6-86356e9a49f5"},{"Application Name":"Office Online Client MSA- Loki","Application IDs":"b6e69c34-5f1f-4c34-8cdf-7fea120b8670"},{"Application Name":"Office Online Core SSO","Application IDs":"243c63a3-247d-41c5-9d83-7788c43f1c43"},{"Application Name":"Office Online Search","Application IDs":"a9b49b65-0a12-430b-9540-c80b3332c127"},{"Application Name":"Office.com","Application IDs":"4b233688-031c-404b-9a80-a4f3f2351f90"},{"Application Name":"Office365 Shell WCSS-Client","Application IDs":"89bee1f7-5e6e-4d8a-9f3d-ecd601259da7"},{"Application Name":"OfficeClientService","Application IDs":"0f698dd4-f011-4d23-a33e-b36416dcb1e6"},{"Application Name":"OfficeHome","Application IDs":"4765445b-32c6-49b0-83e6-1d93765276ca"},{"Application Name":"OfficeShredderWacClient","Application IDs":"4d5c2d63-cf83-4365-853c-925fd1a64357"},{"Application Name":"OMSOctopiPROD","Application IDs":"62256cef-54c0-4cb4-bcac-4c67989bdc40"},{"Application Name":"OneDrive SyncEngine","Application IDs":"ab9b8c07-8f02-4f72-87fa-80105867a763"},{"Application Name":"OneNote","Application IDs":"2d4d3d8e-2be3-4bef-9f87-7875a61c29de"},{"Application Name":"Outlook Mobile","Application IDs":"27922004-5251-4030-b22d-91ecd9a37ea4"},{"Application Name":"Partner Customer Delegated Admin Offline Processor","Application IDs":"a3475900-ccec-4a69-98f5-a65cd5dc5306"},{"Application Name":"Password Breach Authenticator","Application IDs":"bdd48c81-3a58-4ea9-849c-ebea7f6b6360"},{"Application Name":"Power BI Service","Application IDs":"00000009-0000-0000-c000-000000000000"},{"Application Name":"SharedWithMe","Application IDs":"ffcb16e8-f789-467c-8ce9-f826a080d987"},{"Application Name":"SharePoint Online Web Client Extensibility","Application IDs":"08e18876-6177-487e-b8b5-cf950c1e598c"},{"Application Name":"Signup","Application IDs":"b4bddae8-ab25-483e-8670-df09b9f1d0ea"},{"Application Name":"Skype for Business Online","Application IDs":"00000004-0000-0ff1-ce00-000000000000"},{"Application Name":"Sway","Application IDs":"905fcf26-4eb7-48a0-9ff0-8dcc7194b5ba"},{"Application Name":"Universal Store Native Client","Application IDs":"268761a2-03f3-40df-8a8b-c3db24145b6b"},{"Application Name":"Vortex [wsfed enabled]","Application IDs":"5572c4c0-d078-44ce-b81c-6cbf8d3ed39e"},{"Application Name":"Windows Azure Active Directory","Application IDs":"00000002-0000-0000-c000-000000000000"},{"Application Name":"Windows Azure Service Management API","Application IDs":"797f4846-ba00-4fd7-ba43-dac1f8f63013"},{"Application Name":"WindowsDefenderATP Portal","Application IDs":"a3b79187-70b2-4139-83f9-6016c58cd27b"},{"Application Name":"Windows Search","Application IDs":"26a7ee05-5602-4d76-a7ba-eae8b7b67941"},{"Application Name":"Windows Spotlight","Application IDs":"1b3c667f-cde3-4090-b60b-3d2abd0117f0"},{"Application Name":"Windows Store for Business","Application IDs":"45a330b1-b1ec-4cc1-9161-9f03992aa49f"},{"Application Name":"Yammer","Application IDs":"00000005-0000-0ff1-ce00-000000000000"},{"Application Name":"Yammer Web","Application IDs":"c1c74fed-04c9-4704-80dc-9f79a2e515cb"},{"Application Name":"Yammer Web Embed","Application IDs":"e1ef36fd-b883-4dbf-97f0-9ece4b576fc6"}]' | ConvertFrom-Json | Where-Object -Property 'Application IDs' -EQ $AuditlogsLogon.applicationId + $AuditlogsLogon = (New-ExoRequest -tenantid $TenantFilter -cmdlet 'Search-unifiedAuditLog' -cmdParams $SearchParam | Sort-Object -Property CreationDate | Select-Object -Last 1).auditdata | ConvertFrom-Json + $AppName = '[{"Application Name":"ACOM Azure Website","Application IDs":"23523755-3a2b-41ca-9315-f81f3f566a95"},{"Application Name":"AEM-DualAuth","Application IDs":"69893ee3-dd10-4b1c-832d-4870354be3d8"},{"Application Name":"ASM Campaign Servicing","Application IDs":"0cb7b9ec-5336-483b-bc31-b15b5788de71"},{"Application Name":"Azure Advanced Threat Protection","Application IDs":"7b7531ad-5926-4f2d-8a1d-38495ad33e17"},{"Application Name":"Azure Data Lake","Application IDs":"e9f49c6b-5ce5-44c8-925d-015017e9f7ad"},{"Application Name":"Azure Lab Services Portal","Application IDs":"835b2a73-6e10-4aa5-a979-21dfda45231c"},{"Application Name":"Azure Portal","Application IDs":"c44b4083-3bb0-49c1-b47d-974e53cbdf3c"},{"Application Name":"AzureSupportCenter","Application IDs":"37182072-3c9c-4f6a-a4b3-b3f91cacffce"},{"Application Name":"Bing","Application IDs":"9ea1ad79-fdb6-4f9a-8bc3-2b70f96e34c7"},{"Application Name":"CPIM Service","Application IDs":"bb2a2e3a-c5e7-4f0a-88e0-8e01fd3fc1f4"},{"Application Name":"CRM Power BI Integration","Application IDs":"e64aa8bc-8eb4-40e2-898b-cf261a25954f"},{"Application Name":"Dataverse","Application IDs":"00000007-0000-0000-c000-000000000000"},{"Application Name":"Enterprise Roaming and Backup","Application IDs":"60c8bde5-3167-4f92-8fdb-059f6176dc0f"},{"Application Name":"IAM Supportability","Application IDs":"a57aca87-cbc0-4f3c-8b9e-dc095fdc8978"},{"Application Name":"IrisSelectionFrontDoor","Application IDs":"16aeb910-ce68-41d1-9ac3-9e1673ac9575"},{"Application Name":"MCAPI Authorization Prod","Application IDs":"d73f4b35-55c9-48c7-8b10-651f6f2acb2e"},{"Application Name":"Media Analysis and Transformation Service","Application IDs":"944f0bd1-117b-4b1c-af26-804ed95e767e
0cd196ee-71bf-4fd6-a57c-b491ffd4fb1e"},{"Application Name":"Microsoft 365 Support Service","Application IDs":"ee272b19-4411-433f-8f28-5c13cb6fd407"},{"Application Name":"Microsoft App Access Panel","Application IDs":"0000000c-0000-0000-c000-000000000000"},{"Application Name":"Microsoft Approval Management","Application IDs":"65d91a3d-ab74-42e6-8a2f-0add61688c74
38049638-cc2c-4cde-abe4-4479d721ed44"},{"Application Name":"Microsoft Authentication Broker","Application IDs":"29d9ed98-a469-4536-ade2-f981bc1d605e"},{"Application Name":"Microsoft Azure CLI","Application IDs":"04b07795-8ddb-461a-bbee-02f9e1bf7b46"},{"Application Name":"Microsoft Azure PowerShell","Application IDs":"1950a258-227b-4e31-a9cf-717495945fc2"},{"Application Name":"Microsoft Bing Search","Application IDs":"cf36b471-5b44-428c-9ce7-313bf84528de"},{"Application Name":"Microsoft Bing Search for Microsoft Edge","Application IDs":"2d7f3606-b07d-41d1-b9d2-0d0c9296a6e8"},{"Application Name":"Microsoft Bing Default Search Engine","Application IDs":"1786c5ed-9644-47b2-8aa0-7201292175b6"},{"Application Name":"Microsoft Defender for Cloud Apps","Application IDs":"3090ab82-f1c1-4cdf-af2c-5d7a6f3e2cc7"},{"Application Name":"Microsoft Docs","Application IDs":"18fbca16-2224-45f6-85b0-f7bf2b39b3f3"},{"Application Name":"Microsoft Dynamics ERP","Application IDs":"00000015-0000-0000-c000-000000000000"},{"Application Name":"Microsoft Edge Insider Addons Prod","Application IDs":"6253bca8-faf2-4587-8f2f-b056d80998a7"},{"Application Name":"Microsoft Exchange Online Protection","Application IDs":"00000007-0000-0ff1-ce00-000000000000"},{"Application Name":"Microsoft Forms","Application IDs":"c9a559d2-7aab-4f13-a6ed-e7e9c52aec87"},{"Application Name":"Microsoft Graph","Application IDs":"00000003-0000-0000-c000-000000000000"},{"Application Name":"Microsoft Intune Web Company Portal","Application IDs":"74bcdadc-2fdc-4bb3-8459-76d06952a0e9"},{"Application Name":"Microsoft Intune Windows Agent","Application IDs":"fc0f3af4-6835-4174-b806-f7db311fd2f3"},{"Application Name":"Microsoft Learn","Application IDs":"18fbca16-2224-45f6-85b0-f7bf2b39b3f3"},{"Application Name":"Microsoft Office","Application IDs":"d3590ed6-52b3-4102-aeff-aad2292ab01c"},{"Application Name":"Microsoft Office 365 Portal","Application IDs":"00000006-0000-0ff1-ce00-000000000000"},{"Application Name":"Microsoft Office Web Apps Service","Application IDs":"67e3df25-268a-4324-a550-0de1c7f97287"},{"Application Name":"Microsoft Online Syndication Partner Portal","Application IDs":"d176f6e7-38e5-40c9-8a78-3998aab820e7"},{"Application Name":"Microsoft password reset service","Application IDs":"93625bc8-bfe2-437a-97e0-3d0060024faa"},{"Application Name":"Microsoft Power BI","Application IDs":"871c010f-5e61-4fb1-83ac-98610a7e9110"},{"Application Name":"Microsoft Storefronts","Application IDs":"28b567f6-162c-4f54-99a0-6887f387bbcc"},{"Application Name":"Microsoft Stream Portal","Application IDs":"cf53fce8-def6-4aeb-8d30-b158e7b1cf83"},{"Application Name":"Microsoft Substrate Management","Application IDs":"98db8bd6-0cc0-4e67-9de5-f187f1cd1b41"},{"Application Name":"Microsoft Support","Application IDs":"fdf9885b-dd37-42bf-82e5-c3129ef5a302"},{"Application Name":"Microsoft Teams","Application IDs":"1fec8e78-bce4-4aaf-ab1b-5451cc387264"},{"Application Name":"Microsoft Teams Services","Application IDs":"cc15fd57-2c6c-4117-a88c-83b1d56b4bbe"},{"Application Name":"Microsoft Teams Web Client","Application IDs":"5e3ce6c0-2b1f-4285-8d4b-75ee78787346"},{"Application Name":"Microsoft Whiteboard Services","Application IDs":"95de633a-083e-42f5-b444-a4295d8e9314"},{"Application Name":"O365 Suite UX","Application IDs":"4345a7b9-9a63-4910-a426-35363201d503"},{"Application Name":"Office 365 Exchange Online","Application IDs":"00000002-0000-0ff1-ce00-000000000000"},{"Application Name":"Office 365 Management","Application IDs":"00b41c95-dab0-4487-9791-b9d2c32c80f2"},{"Application Name":"Office 365 Search Service","Application IDs":"66a88757-258c-4c72-893c-3e8bed4d6899"},{"Application Name":"Office 365 SharePoint Online","Application IDs":"00000003-0000-0ff1-ce00-000000000000"},{"Application Name":"Office Delve","Application IDs":"94c63fef-13a3-47bc-8074-75af8c65887a"},{"Application Name":"Office Online Add-in SSO","Application IDs":"93d53678-613d-4013-afc1-62e9e444a0a5"},{"Application Name":"Office Online Client AAD- Augmentation Loop","Application IDs":"2abdc806-e091-4495-9b10-b04d93c3f040"},{"Application Name":"Office Online Client AAD- Loki","Application IDs":"b23dd4db-9142-4734-867f-3577f640ad0c"},{"Application Name":"Office Online Client AAD- Maker","Application IDs":"17d5e35f-655b-4fb0-8ae6-86356e9a49f5"},{"Application Name":"Office Online Client MSA- Loki","Application IDs":"b6e69c34-5f1f-4c34-8cdf-7fea120b8670"},{"Application Name":"Office Online Core SSO","Application IDs":"243c63a3-247d-41c5-9d83-7788c43f1c43"},{"Application Name":"Office Online Search","Application IDs":"a9b49b65-0a12-430b-9540-c80b3332c127"},{"Application Name":"Office.com","Application IDs":"4b233688-031c-404b-9a80-a4f3f2351f90"},{"Application Name":"Office365 Shell WCSS-Client","Application IDs":"89bee1f7-5e6e-4d8a-9f3d-ecd601259da7"},{"Application Name":"OfficeClientService","Application IDs":"0f698dd4-f011-4d23-a33e-b36416dcb1e6"},{"Application Name":"OfficeHome","Application IDs":"4765445b-32c6-49b0-83e6-1d93765276ca"},{"Application Name":"OfficeShredderWacClient","Application IDs":"4d5c2d63-cf83-4365-853c-925fd1a64357"},{"Application Name":"OMSOctopiPROD","Application IDs":"62256cef-54c0-4cb4-bcac-4c67989bdc40"},{"Application Name":"OneDrive SyncEngine","Application IDs":"ab9b8c07-8f02-4f72-87fa-80105867a763"},{"Application Name":"OneNote","Application IDs":"2d4d3d8e-2be3-4bef-9f87-7875a61c29de"},{"Application Name":"Outlook Mobile","Application IDs":"27922004-5251-4030-b22d-91ecd9a37ea4"},{"Application Name":"Partner Customer Delegated Admin Offline Processor","Application IDs":"a3475900-ccec-4a69-98f5-a65cd5dc5306"},{"Application Name":"Password Breach Authenticator","Application IDs":"bdd48c81-3a58-4ea9-849c-ebea7f6b6360"},{"Application Name":"Power BI Service","Application IDs":"00000009-0000-0000-c000-000000000000"},{"Application Name":"SharedWithMe","Application IDs":"ffcb16e8-f789-467c-8ce9-f826a080d987"},{"Application Name":"SharePoint Online Web Client Extensibility","Application IDs":"08e18876-6177-487e-b8b5-cf950c1e598c"},{"Application Name":"Signup","Application IDs":"b4bddae8-ab25-483e-8670-df09b9f1d0ea"},{"Application Name":"Skype for Business Online","Application IDs":"00000004-0000-0ff1-ce00-000000000000"},{"Application Name":"Sway","Application IDs":"905fcf26-4eb7-48a0-9ff0-8dcc7194b5ba"},{"Application Name":"Universal Store Native Client","Application IDs":"268761a2-03f3-40df-8a8b-c3db24145b6b"},{"Application Name":"Vortex [wsfed enabled]","Application IDs":"5572c4c0-d078-44ce-b81c-6cbf8d3ed39e"},{"Application Name":"Windows Azure Active Directory","Application IDs":"00000002-0000-0000-c000-000000000000"},{"Application Name":"Windows Azure Service Management API","Application IDs":"797f4846-ba00-4fd7-ba43-dac1f8f63013"},{"Application Name":"WindowsDefenderATP Portal","Application IDs":"a3b79187-70b2-4139-83f9-6016c58cd27b"},{"Application Name":"Windows Search","Application IDs":"26a7ee05-5602-4d76-a7ba-eae8b7b67941"},{"Application Name":"Windows Spotlight","Application IDs":"1b3c667f-cde3-4090-b60b-3d2abd0117f0"},{"Application Name":"Windows Store for Business","Application IDs":"45a330b1-b1ec-4cc1-9161-9f03992aa49f"},{"Application Name":"Yammer","Application IDs":"00000005-0000-0ff1-ce00-000000000000"},{"Application Name":"Yammer Web","Application IDs":"c1c74fed-04c9-4704-80dc-9f79a2e515cb"},{"Application Name":"Yammer Web Embed","Application IDs":"e1ef36fd-b883-4dbf-97f0-9ece4b576fc6"}]' | + ConvertFrom-Json | Where-Object -Property 'Application IDs' -EQ $AuditlogsLogon.applicationId $LastSignIn = [PSCustomObject]@{ AppDisplayName = if ($AppName) { $AppName.'Application Name' } else { "$($AuditlogsLogon.Workload) - $($AuditlogsLogon.ApplicationId) " } CreatedDateTime = $AuditlogsLogon.CreationTime @@ -75,7 +75,7 @@ Function Invoke-ListUsers { @{ Name = 'LastSigninDate'; Expression = { $($LastSignIn.CreatedDateTime | Out-String) } }, @{ Name = 'LastSigninStatus'; Expression = { $AuditlogsLogon.operation } }, @{ Name = 'LastSigninResult'; Expression = { $LastSignIn.status } }, - @{ Name = 'LastSigninFailureReason'; Expression = { if ($LastSignIn.Id -eq 0) { 'Sucessfully signed in' } else { $LastSignIn.Id } } } + @{ Name = 'LastSigninFailureReason'; Expression = { if ($LastSignIn.Id -eq 0) { 'Successfully signed in' } else { $LastSignIn.Id } } } } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAuditLogs.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAuditLogs.ps1 index 9915eef063b7..a41726c72e57 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAuditLogs.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAuditLogs.ps1 @@ -8,26 +8,31 @@ function Invoke-ListAuditLogs { [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = 'ListAuditLogs' - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - $TenantFilter = $Request.Query.TenantFilter + # Interact with query parameters or the body of the request. + $TenantFilter = $Request.Query.tenantFilter + $LogID = $Request.Query.LogId + $StartDate = $Request.Query.StartDate + $EndDate = $Request.Query.EndDate + $RelativeTime = $Request.Query.RelativeTime $FilterConditions = [System.Collections.Generic.List[string]]::new() - if ($Request.Query.LogId) { - $FilterConditions.Add("RowKey eq '$($Request.Query.LogId)'") + if ($LogID) { + $FilterConditions.Add("RowKey eq '$($LogID)'") } else { if ($TenantFilter -and $TenantFilter -ne 'AllTenants') { $FilterConditions.Add("Tenant eq '$TenantFilter'") } - if (!$Request.Query.StartDate -and !$Request.Query.EndDate -and !$Request.Query.RelativeTime) { - $Request.Query.StartDate = (Get-Date).AddDays(-7).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ') - $Request.Query.EndDate = (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ') + if (!$StartDate -and !$EndDate -and !$RelativeTime) { + $StartDate = (Get-Date).AddDays(-7).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ') + $EndDate = (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ') } - if ($Request.Query.RelativeTime) { - $RelativeTime = $Request.Query.RelativeTime + if ($RelativeTime) { if ($RelativeTime -match '(\d+)([dhm])') { $EndDate = (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ') @@ -40,19 +45,19 @@ function Invoke-ListAuditLogs { } $FilterConditions.Add("Timestamp ge datetime'$StartDate' and Timestamp le datetime'$EndDate'") } else { - if ($Request.Query.StartDate) { - if ($Request.Query.StartDate -match '^\d+$') { - $StartDate = [DateTimeOffset]::FromUnixTimeSeconds([int]$Request.Query.StartDate).DateTime.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ') + if ($StartDate) { + if ($StartDate -match '^\d+$') { + $StartDate = [DateTimeOffset]::FromUnixTimeSeconds([int]$StartDate).DateTime.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ') } else { - $StartDate = (Get-Date $Request.Query.StartDate).ToString('yyyy-MM-ddTHH:mm:ssZ') + $StartDate = (Get-Date $StartDate).ToString('yyyy-MM-ddTHH:mm:ssZ') } $FilterConditions.Add("Timestamp ge datetime'$StartDate'") - if ($Request.Query.EndDate) { - if ($Request.Query.EndDate -match '^\d+$') { - $EndDate = [DateTimeOffset]::FromUnixTimeSeconds([int]$Request.Query.EndDate).DateTime.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ') + if ($EndDate) { + if ($EndDate -match '^\d+$') { + $EndDate = [DateTimeOffset]::FromUnixTimeSeconds([int]$EndDate).DateTime.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ') } else { - $EndDate = (Get-Date $Request.Query.EndDate).ToString('yyyy-MM-ddTHH:mm:ssZ') + $EndDate = (Get-Date $EndDate).ToString('yyyy-MM-ddTHH:mm:ssZ') } $FilterConditions.Add("Timestamp le datetime'$EndDate'") } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListConditionalAccessPolicies.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListConditionalAccessPolicies.ps1 index 25b28cc46a09..c96c3b99f044 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListConditionalAccessPolicies.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListConditionalAccessPolicies.ps1 @@ -11,7 +11,7 @@ Function Invoke-ListConditionalAccessPolicies { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + Write-LogMessage -headers $Request.Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' function Get-LocationNameFromId { @@ -114,11 +114,8 @@ Function Invoke-ListConditionalAccessPolicies { return $return } - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - # Interact with query parameters or the body of the request. - $TenantFilter = $Request.Query.TenantFilter + $TenantFilter = $Request.Query.tenantFilter try { $Requests = @( @{ @@ -158,7 +155,7 @@ Function Invoke-ListConditionalAccessPolicies { } ) - $GraphRequest = New-GraphBulkRequest -Requests $Requests -tenantid $tenantfilter -asapp $true + $GraphRequest = New-GraphBulkRequest -Requests $Requests -tenantid $TenantFilter -asapp $true $ConditionalAccessPolicyOutput = ($GraphRequest | Where-Object { $_.id -eq 'policies' }).body.value $AllNamedLocations = ($GraphRequest | Where-Object { $_.id -eq 'namedLocations' }).body.value diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListConditionalAccessPolicyChanges.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListConditionalAccessPolicyChanges.ps1 index b21fbe522b11..b144805a6670 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListConditionalAccessPolicyChanges.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListConditionalAccessPolicyChanges.ps1 @@ -11,39 +11,36 @@ Function Invoke-ListConditionalAccessPolicyChanges { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + $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. - $TenantFilter = $Request.Query.TenantFilter - $policyId = $Request.body.id - $policyDisplayName = $Request.body.displayName + $TenantFilter = $Request.Query.tenantFilter + $PolicyId = $Request.Query.id + $PolicyDisplayName = $Request.Query.displayName try { - [array]$changes = New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/auditLogs/directoryAudits?`$filter=targetResources/any(s:s/id eq '$($policyId)')" -tenantid $TenantFilter | ForEach-Object { + [array]$Changes = New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/auditLogs/directoryAudits?`$filter=targetResources/any(s:s/id eq '$($PolicyId)')" -tenantid $TenantFilter | ForEach-Object { [pscustomobject]@{ - policy = $policyDisplayName - policyId = $policyId + policy = $PolicyDisplayName + policyId = $PolicyId typeFriendlyName = $_.activityDisplayName - type = $_.operationType - initiatedBy = if ($_.initiatedBy.user.userPrincipalName) { $_.initiatedBy.user.userPrincipalName } else { $_.initiatedBy.app.displayName } - date = $_.activityDateTime - oldValue = ($_.targetResources[0].modifiedProperties.oldValue | ConvertFrom-Json) # targetResources is an array, can we ever get more than 1 object in it? - newValue = ($_.targetResources[0].modifiedProperties.newValue | ConvertFrom-Json) + type = $_.operationType + initiatedBy = if ($_.initiatedBy.user.userPrincipalName) { $_.initiatedBy.user.userPrincipalName } else { $_.initiatedBy.app.displayName } + date = $_.activityDateTime + oldValue = ($_.targetResources[0].modifiedProperties.oldValue | ConvertFrom-Json) # targetResources is an array, can we ever get more than 1 object in it? + newValue = ($_.targetResources[0].modifiedProperties.newValue | ConvertFrom-Json) } } $StatusCode = [HttpStatusCode]::OK } catch { $StatusCode = [HttpStatusCode]::BadRequest - Write-Host $($_.Exception.message) - Write-LogMessage -headers $Request.Headers -API $APIName -message "Failed to request audit logs for policy $($policyDisplayName): $($_.Exception.message)" -Sev "Error" -tenant $TenantFilter + $Changes = "Failed to request audit logs for policy $($PolicyDisplayName): $($_.Exception.message)" } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $StatusCode - Body = $changes - }) + StatusCode = $StatusCode + Body = @($Changes) + }) } From ff41a68b54320be0c17a36ec0f170b9f8c3c4b5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sat, 22 Feb 2025 18:35:56 +0100 Subject: [PATCH 043/167] remove unused endpoint --- .../Email-Exchange/Invoke-ListRecipients.ps1 | 47 ------------------- 1 file changed, 47 deletions(-) delete mode 100644 Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListRecipients.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListRecipients.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListRecipients.ps1 deleted file mode 100644 index 69d049c13ae9..000000000000 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListRecipients.ps1 +++ /dev/null @@ -1,47 +0,0 @@ -using namespace System.Net - -Function Invoke-ListRecipients { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.Mailbox.Read - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - - # Interact with query parameters or the body of the request. - $TenantFilter = $Request.Query.TenantFilter - try { - $Select = 'id,DisplayName,ExchangeGuid,ArchiveGuid,PrimarySmtpAddress,PrimarySMTPAddress,RecipientType,RecipientTypeDetails,EmailAddresses' - $ExoRequest = @{ - tenantid = $TenantFilter - cmdlet = 'Get-Recipient' - cmdParams = @{resultsize = 'unlimited' } - Select = $select - } - - $GraphRequest = (New-ExoRequest @ExoRequest) | Select-Object id, ExchangeGuid, ArchiveGuid, - @{ Name = 'UPN'; Expression = { $_.'PrimarySmtpAddress' } }, - @{ Name = 'mail'; Expression = { $_.'PrimarySmtpAddress' } }, - @{ Name = 'displayName'; Expression = { $_.'DisplayName' } } - $StatusCode = [HttpStatusCode]::OK - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - $StatusCode = [HttpStatusCode]::Forbidden - $GraphRequest = $ErrorMessage - } - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $StatusCode - Body = @($GraphRequest) - }) - -} From d26e45790f8f84283b41992b29822fe72b3cea0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sat, 22 Feb 2025 18:36:02 +0100 Subject: [PATCH 044/167] Refactor tenant filter handling and improve logging consistency across API endpoints --- .../CIPP/Settings/Invoke-ExecCPVPermissions.ps1 | 8 +++----- .../Tenant/Administration/Invoke-SetAuthMethod.ps1 | 8 +++++++- .../Entrypoints/Invoke-ListFunctionStats.ps1 | 14 ++++++++------ .../Invoke-ListMailboxMobileDevices.ps1 | 7 ++----- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCPVPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCPVPermissions.ps1 index 663468180762..ae464286d3cc 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCPVPermissions.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCPVPermissions.ps1 @@ -12,17 +12,15 @@ Function Invoke-ExecCPVPermissions { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $TenantFilter = $TenantFilter - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - $Tenant = Get-Tenants -IncludeAll | Where-Object -Property customerId -EQ $Request.Body.TenantFilter | Select-Object -First 1 + $Tenant = Get-Tenants -IncludeAll | Where-Object -Property customerId -EQ $TenantFilter | Select-Object -First 1 if ($Tenant) { Write-Host "Our tenant is $($Tenant.displayName) - $($Tenant.defaultDomainName)" - $TenantFilter = $Request.Body.TenantFilter $CPVConsentParams = @{ - TenantFilter = $Request.Body.TenantFilter + TenantFilter = $TenantFilter } if ($Request.Query.ResetSP -eq 'true') { $CPVConsentParams.ResetSP = $true diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-SetAuthMethod.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-SetAuthMethod.ps1 index 26653bf43648..9e089ff3f77c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-SetAuthMethod.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-SetAuthMethod.ps1 @@ -8,11 +8,17 @@ function Invoke-SetAuthMethod { Param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint + $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. $State = if ($Request.Body.state -eq 'enabled') { $true } else { $false } $TenantFilter = $Request.Body.tenantFilter + $AuthenticationMethodId = $Request.Body.Id + try { - $Result = Set-CIPPAuthenticationPolicy -Tenant $TenantFilter -APIName $APIName -AuthenticationMethodId $($Request.Body.Id) -Enabled $State -Headers $Request.Headers + $Result = Set-CIPPAuthenticationPolicy -Tenant $TenantFilter -APIName $APIName -AuthenticationMethodId $AuthenticationMethodId -Enabled $State -Headers $Headers $StatusCode = [HttpStatusCode]::OK } catch { $Result = $_ diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionStats.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionStats.ps1 index 257d6c32e6cb..9bcb80aca64e 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionStats.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionStats.ps1 @@ -14,19 +14,21 @@ Function Invoke-ListFunctionStats { Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' try { - $TenantFilter = $Request.Query.TenantFilter + $TenantFilter = $Request.Query.tenantFilter $PartitionKey = $Request.Query.FunctionType + $Time = $Request.Query.Time + $Interval = $Request.Query.Interval - $Timestamp = if (![string]::IsNullOrEmpty($Request.Query.Interval) -and ![string]::IsNullOrEmpty($Request.Query.Time)) { - switch ($Request.Query.Interval) { + $Timestamp = if (![string]::IsNullOrEmpty($Interval) -and ![string]::IsNullOrEmpty($Time)) { + switch ($Interval) { 'Days' { - (Get-Date).AddDays(-$Request.Query.Time).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss.fffK') + (Get-Date).AddDays(-$Time).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss.fffK') } 'Hours' { - (Get-Date).AddHours(-$Request.Query.Time).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss.fffK') + (Get-Date).AddHours(-$Time).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss.fffK') } 'Minutes' { - (Get-Date).AddMinutes(-$Request.Query.Time).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss.fffK') + (Get-Date).AddMinutes(-$Time).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss.fffK') } } } else { diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxMobileDevices.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxMobileDevices.ps1 index b09540ed117f..3e1be65549a6 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxMobileDevices.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxMobileDevices.ps1 @@ -14,11 +14,8 @@ Function Invoke-ListMailboxMobileDevices { Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - # Interact with query parameters or the body of the request. - $TenantFilter = $Request.Query.TenantFilter + $TenantFilter = $Request.Query.tenantFilter $Mailbox = $Request.Query.Mailbox Write-Host $TenantFilter @@ -28,7 +25,7 @@ Function Invoke-ListMailboxMobileDevices { $base64IdentityParam = [Convert]::ToBase64String($Bytes) try { - $GraphRequest = New-GraphGetRequest -uri "https://outlook.office365.com:443/adminapi/beta/$($TenantFilter)/mailbox('$($base64IdentityParam)')/MobileDevice/Exchange.GetMobileDeviceStatistics()/?IsEncoded=True" -Tenantid $tenantfilter -scope ExchangeOnline | Select-Object @{ Name = 'clientType'; Expression = { $_.ClientType } }, + $GraphRequest = New-GraphGetRequest -uri "https://outlook.office365.com:443/adminapi/beta/$($TenantFilter)/mailbox('$($base64IdentityParam)')/MobileDevice/Exchange.GetMobileDeviceStatistics()/?IsEncoded=True" -Tenantid $TenantFilter -scope ExchangeOnline | Select-Object @{ Name = 'clientType'; Expression = { $_.ClientType } }, @{ Name = 'clientVersion'; Expression = { $_.ClientVersion } }, @{ Name = 'deviceAccessState'; Expression = { $_.DeviceAccessState } }, @{ Name = 'deviceFriendlyName'; Expression = { if ([string]::IsNullOrEmpty($_.DeviceFriendlyName)) { 'Unknown' }else { $_.DeviceFriendlyName } } }, From ca9a6584fce8dacf96505d3f68694350d425903e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sun, 23 Feb 2025 17:54:28 +0100 Subject: [PATCH 045/167] Various modernizations and GET to POST refactoring --- .../CIPP/Core/Invoke-ExecListBackup.ps1 | 25 ++++++++++++------ .../CIPP/Core/Invoke-GetVersion.ps1 | 3 +-- .../CIPP/Core/Invoke-ListApiTest.ps1 | 1 + .../CIPP/Core/invoke-ListEmptyResults.ps1 | 1 + .../Scheduler/Invoke-ListScheduledItems.ps1 | 25 +++++++++++------- .../Invoke-ExecGroupsDelete.ps1 | 24 +++++++++-------- .../Invoke-ExecGroupsDeliveryManagement.ps1 | 25 +++++++++--------- .../Invoke-ExecGroupsHideFromGAL.ps1 | 20 +++++++++----- .../Email-Exchange/Invoke-ExecHideFromGAL.ps1 | 4 +-- ...Invoke-ExecStartManagedFolderAssistant.ps1 | 26 ++++++++++--------- Modules/CIPPCore/Public/Remove-CIPPGroup.ps1 | 11 ++++---- .../Public/Set-CIPPGroupAuthentication.ps1 | 10 ++++--- .../CIPPCore/Public/Set-CIPPHideFromGAL.ps1 | 2 +- 13 files changed, 104 insertions(+), 73 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecListBackup.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecListBackup.ps1 index 013317b805b6..fe9fa4b02aae 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecListBackup.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecListBackup.ps1 @@ -10,23 +10,32 @@ Function Invoke-ExecListBackup { [CmdletBinding()] param($Request, $TriggerMetadata) + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + $Type = $Request.Query.Type + $TenantFilter = $Request.Query.tenantFilter + $NameOnly = $Request.Query.NameOnly + $BackupName = $Request.Query.BackupName + $CippBackupParams = @{} - if ($Request.Query.Type) { - $CippBackupParams.Type = $Request.Query.Type + if ($Type) { + $CippBackupParams.Type = $Type } - if ($Request.Query.TenantFilter) { - $CippBackupParams.TenantFilter = $Request.Query.TenantFilter + if ($TenantFilter) { + $CippBackupParams.TenantFilter = $TenantFilter } - if ($Request.Query.NameOnly) { + if ($NameOnly) { $CippBackupParams.NameOnly = $true } - if ($Request.Query.BackupName) { - $CippBackupParams.Name = $Request.Query.BackupName + if ($BackupName) { + $CippBackupParams.Name = $BackupName } $Result = Get-CIPPBackup @CippBackupParams - if ($request.Query.NameOnly) { + if ($NameOnly) { $Result = $Result | Select-Object @{Name = 'BackupName'; exp = { $_.RowKey } }, Timestamp | Sort-Object Timestamp -Descending } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetVersion.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetVersion.ps1 index 6bc115e7e4f0..2a81fc1203a8 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetVersion.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetVersion.ps1 @@ -13,10 +13,9 @@ Function Invoke-GetVersion { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - $CIPPVersion = $request.query.localversion + $CIPPVersion = $request.query.LocalVersion $Version = Assert-CippVersion -CIPPVersion $CIPPVersion - # Write to the Azure Functions log stream. # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListApiTest.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListApiTest.ps1 index b8ba63e8a322..63c63d1637ca 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListApiTest.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListApiTest.ps1 @@ -8,6 +8,7 @@ function Invoke-ListApiTest { [CmdletBinding()] param($Request, $TriggerMetadata) + # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK Body = ($Request | ConvertTo-Json -Depth 5) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/invoke-ListEmptyResults.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/invoke-ListEmptyResults.ps1 index c0497528c42a..a41cdddebb13 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/invoke-ListEmptyResults.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/invoke-ListEmptyResults.ps1 @@ -11,6 +11,7 @@ Function invoke-ListEmptyResults { param($Request, $TriggerMetadata) + # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK Body = @() 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 e8a5c5575739..025e8516b05a 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 @@ -10,35 +10,42 @@ Function Invoke-ListScheduledItems { [CmdletBinding()] param($Request, $TriggerMetadata) - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + $APIName = $Request.Params.CIPPEndpoint + $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 ($Request.Query.ShowHidden) { + if ($ShowHidden -eq $true) { $ScheduledItemFilter.Add('Hidden eq true') } else { $ScheduledItemFilter.Add('Hidden eq false') } - if ($Request.Query.Name) { - $ScheduledItemFilter.Add("Name eq '$($Request.Query.Name)'") + if ($Name -eq $true) { + $ScheduledItemFilter.Add("Name eq '$($Name)'") } $Filter = $ScheduledItemFilter -join ' and ' Write-Host "Filter: $Filter" $Table = Get-CIPPTable -TableName 'ScheduledTasks' - if ($Request.Query.Showhidden -eq $true) { + if ($ShowHidden -eq $true) { $HiddenTasks = $false } else { $HiddenTasks = $true } $Tasks = Get-CIPPAzDataTableEntity @Table -Filter $Filter | Where-Object { $_.Hidden -ne $HiddenTasks } - if ($Request.Query.Type) { - $tasks.Command - $Tasks = $Tasks | Where-Object { $_.command -eq $Request.Query.Type } + if ($Type) { + $Tasks.Command + $Tasks = $Tasks | Where-Object { $_.command -eq $Type } } $AllowedTenants = Test-CIPPAccess -Request $Request -TenantList diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDelete.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDelete.ps1 index 6dc149972be2..ec24ebf11a38 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDelete.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDelete.ps1 @@ -11,24 +11,26 @@ Function Invoke-ExecGroupsDelete { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - + $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. + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $GroupType = $Request.Query.GroupType ?? $Request.Body.GroupType + $ID = $Request.Query.id ?? $Request.Body.id + $DisplayName = $Request.Query.displayName ?? $Request.Body.displayName + Try { - $RemoveResults = Remove-CIPPGroup -ID $Request.query.id -GroupType $Request.query.GroupType -tenantFilter $Request.query.TenantFilter -displayName $Request.query.displayName -APIName $APINAME -Headers $Request.Headers - $Results = [pscustomobject]@{'Results' = $RemoveResults } + $Result = Remove-CIPPGroup -ID $ID -Grouptype $GroupType -TenantFilter $TenantFilter -DisplayName $DisplayName -APIName $APIName -Headers $Headers + $StatusCode = [HttpStatusCode]::OK } catch { - $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" } + $Result = "$($_.Exception.Message)" + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Results + StatusCode = $StatusCode + Body = @{Results = $Result } }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDeliveryManagement.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDeliveryManagement.ps1 index 5d7c0c45bc92..6966ad72c0e2 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDeliveryManagement.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDeliveryManagement.ps1 @@ -11,25 +11,26 @@ Function Invoke-ExecGroupsDeliveryManagement { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - + $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. + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $GroupType = $Request.Query.GroupType ?? $Request.Body.GroupType + $OnlyAllowInternal = $Request.Query.OnlyAllowInternal ?? $Request.Body.OnlyAllowInternal + $ID = $Request.Query.ID ?? $Request.Body.ID + Try { - $SetResults = Set-CIPPGroupAuthentication -ID $Request.query.id -GroupType $Request.query.GroupType -OnlyAllowInternalString $Request.query.OnlyAllowInternal -tenantFilter $Request.query.TenantFilter -APIName $APINAME -Headers $Request.Headers - $Results = [pscustomobject]@{'Results' = $SetResults } + $Result = Set-CIPPGroupAuthentication -ID $ID -GroupType $GroupType -OnlyAllowInternalString $OnlyAllowInternal -tenantFilter $TenantFilter -APIName $APIName -Headers $Headers + $StatusCode = [HttpStatusCode]::OK } catch { - $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" } - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($tenantfilter) -message "Delivery Management failed: $($_.Exception.Message)" -Sev 'Error' + $Result = "$($_.Exception.Message)" + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Results + StatusCode = $StatusCode + Body = @{ Results = $Result } }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsHideFromGAL.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsHideFromGAL.ps1 index b8bfa298cf6c..d12ed019b26c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsHideFromGAL.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsHideFromGAL.ps1 @@ -11,20 +11,26 @@ Function Invoke-ExecGroupsHideFromGAL { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $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. + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $GroupType = $Request.Query.GroupType ?? $Request.Body.GroupType + $GroupID = $Request.Query.ID ?? $Request.Body.ID + $HideFromGAL = $Request.Query.HideFromGAL ?? $Request.Body.HideFromGAL + Try { - $GroupStatus = Set-CIPPGroupGAL -Id $Request.query.id -tenantFilter $Request.query.TenantFilter -GroupType $Request.query.groupType -HiddenString $Request.query.HidefromGAL -APIName $APINAME -Headers $Request.Headers - $Results = [pscustomobject]@{'Results' = $GroupStatus } + $Result = Set-CIPPGroupGAL -Id $GroupID -TenantFilter $TenantFilter -GroupType $GroupType -HiddenString $HideFromGAL -APIName $APIName -Headers $Headers + $StatusCode = [HttpStatusCode]::OK } catch { - $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" } - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($tenantfilter) -message "Hide/UnHide from GAL failed: $($_.Exception.Message)" -Sev 'Error' + $Result = "$($_.Exception.Message)" + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Results + StatusCode = $StatusCode + Body = @{'Results' = $Result } }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecHideFromGAL.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecHideFromGAL.ps1 index 21b234e9bfd5..e926564f1f4f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecHideFromGAL.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecHideFromGAL.ps1 @@ -18,8 +18,8 @@ Function Invoke-ExecHideFromGAL { # Support if the request is a POST or a GET. So to support legacy(GET) and new(POST) requests $UserId = $Request.Query.ID ?? $Request.body.ID $TenantFilter = $Request.Query.TenantFilter ?? $Request.body.tenantFilter - $Hidden = -not [string]::IsNullOrWhiteSpace($Request.Query.HideFromGAL) ? [System.Convert]::ToBoolean($Request.Query.HideFromGAL) : [System.Convert]::ToBoolean($Request.body.HideFromGAL) - + $HideFromGAL = $Request.Query.HideFromGAL ?? $Request.body.HideFromGAL + $HideFromGAL = [System.Convert]::ToBoolean($HideFromGAL) Try { $HideResults = Set-CIPPHideFromGAL -tenantFilter $TenantFilter -UserID $UserId -hidefromgal $Hidden -Headers $Request.Headers -APIName $APIName diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 index 962d6a02d316..d9eb6ad3817f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 @@ -11,28 +11,30 @@ Function Invoke-ExecStartManagedFolderAssistant { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $User = $Request.Headers - $Tenant = $Request.query.TenantFilter - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -Headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - $Results = [System.Collections.Generic.List[Object]]::new() # Interact with query parameters or the body of the request. + $Tenant = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $ID = $Request.Query.ID ?? $Request.Body.ID try { - $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Start-ManagedFolderAssistant' -cmdparams @{Identity = $Request.query.id } - $Results.Add("Successfully started Managed Folder Assistant for mailbox $($Request.query.id).") + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Start-ManagedFolderAssistant' -cmdParams @{Identity = $ID } + $Result = "Successfully started Managed Folder Assistant for mailbox $($ID)." + $Severity = 'Info' $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -tenant $Tenant -message "Failed to create room: $($MailboxObject.DisplayName). Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage - $Results.Add("Failed to start Managed Folder Assistant for mailbox $($Request.query.id). Error: $($ErrorMessage.NormalizedError)") - $StatusCode = [HttpStatusCode]::Forbidden + $Result = "Failed to start Managed Folder Assistant for mailbox $($ID). Error: $($ErrorMessage.NormalizedError)" + $Severity = 'Error' + $StatusCode = [HttpStatusCode]::InternalServerError + } finally { + Write-LogMessage -Headers $Headers -API $APIName -tenant $Tenant -message $Result -Sev $Severity -LogData $ErrorMessage + } - $Body = [pscustomobject] @{ 'Results' = @($Results) } + $Body = [pscustomobject] @{ 'Results' = $Result } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = $StatusCode diff --git a/Modules/CIPPCore/Public/Remove-CIPPGroup.ps1 b/Modules/CIPPCore/Public/Remove-CIPPGroup.ps1 index b356dd990b3a..3f1bdafec13a 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPGroup.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPGroup.ps1 @@ -11,20 +11,21 @@ function Remove-CIPPGroup { try { if ($GroupType -eq 'Distribution List' -or $GroupType -eq 'Mail-Enabled Security') { - New-ExoRequest -tenantid $TenantFilter -cmdlet 'Remove-DistributionGroup' -cmdParams @{Identity = $id; BypassSecurityGroupManagerCheck = $true } -useSystemMailbox $true - Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenantfilter) -message "$($DisplayName) Deleted" -Sev 'Info' + New-ExoRequest -tenantid $TenantFilter -cmdlet 'Remove-DistributionGroup' -cmdParams @{Identity = $ID; BypassSecurityGroupManagerCheck = $true } -useSystemMailbox $true + Write-LogMessage -headers $Headers -API $APINAME -tenant $($TenantFilter) -message "$($DisplayName) Deleted" -Sev 'Info' return "Successfully Deleted $($GroupType) group $($DisplayName)" } elseif ($GroupType -eq 'Microsoft 365' -or $GroupType -eq 'Security') { $null = New-GraphPostRequest -uri "https://graph.microsoft.com/v1.0/groups/$($ID)" -tenantid $TenantFilter -type Delete -verbose - Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenantfilter) -message "$($DisplayName) Deleted" -Sev 'Info' + Write-LogMessage -headers $Headers -API $APINAME -tenant $($TenantFilter) -message "$($DisplayName) Deleted" -Sev 'Info' return "Successfully Deleted $($GroupType) group $($DisplayName)" } } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers -API $APIName -message "Could not delete $DisplayName. Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - return "Could not delete $DisplayName. Error: $($ErrorMessage.NormalizedError)" + $Message = "Could not delete $DisplayName. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + throw $Message } } diff --git a/Modules/CIPPCore/Public/Set-CIPPGroupAuthentication.ps1 b/Modules/CIPPCore/Public/Set-CIPPGroupAuthentication.ps1 index 6fca31b53dbf..561670eae554 100644 --- a/Modules/CIPPCore/Public/Set-CIPPGroupAuthentication.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPGroupAuthentication.ps1 @@ -19,11 +19,13 @@ function Set-CIPPGroupAuthentication( return "$GroupType's group cannot have this setting changed" } - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message "$Id set to allow messages from people $messageSuffix" -Sev 'Info' - return "Set $GroupType group $Id to allow messages from people $messageSuffix" + $Message = "Successfully set $GroupType group $Id to allow messages from people $messageSuffix" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Message -Sev 'Info' + return $Message } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message "Delivery Management failed: $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage - return "Failed. $($ErrorMessage.NormalizedError)" + $Message = "Failed to set Delivery Management: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Message -Sev 'Error' -LogData $ErrorMessage + return $Message } } diff --git a/Modules/CIPPCore/Public/Set-CIPPHideFromGAL.ps1 b/Modules/CIPPCore/Public/Set-CIPPHideFromGAL.ps1 index b34daface0e1..5ce6cf6726be 100644 --- a/Modules/CIPPCore/Public/Set-CIPPHideFromGAL.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPHideFromGAL.ps1 @@ -10,7 +10,7 @@ function Set-CIPPHideFromGAL { $Text = if ($HideFromGAL) { 'hidden' } else { 'unhidden' } try { $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Set-Mailbox' -cmdParams @{Identity = $UserId ; HiddenFromAddressListsEnabled = $HideFromGAL } - Write-LogMessage -headers $Headers -API $APINAME -tenant $($Tenantfilter) -message "$($UserId) $Text from GAL" -Sev Info + Write-LogMessage -headers $Headers -API $APIName -tenant $($TenantFilter) -message "$($UserId) $Text from GAL" -Sev Info return "Successfully $Text $($UserId) from GAL." } catch { $ErrorMessage = Get-CippException -Exception $_ From 0d81d82a3f9477bc692e2fdc060fb328fc02db27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sun, 23 Feb 2025 20:36:15 +0100 Subject: [PATCH 046/167] Refactor API functions to improve parameter handling and logging consistency --- .../Email-Exchange/Invoke-ExecCopyForSent.ps1 | 25 ++++++++++--------- .../Invoke-ExecSetMailboxLocale.ps1 | 24 +++++++++++------- .../CIPPCore/Public/Set-CIPPMailboxLocale.ps1 | 10 +++++--- .../CIPPCore/Public/Set-CIPPMessageCopy.ps1 | 14 ++++++----- 4 files changed, 42 insertions(+), 31 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecCopyForSent.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecCopyForSent.ps1 index f3f9b27e6b11..4d0707ac66f9 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecCopyForSent.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecCopyForSent.ps1 @@ -11,26 +11,27 @@ Function Invoke-ExecCopyForSent { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - + $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. + $TenantFilter = $Request.Query.TenantFilter ?? $Request.Body.TenantFilter + $UserID = $Request.Query.ID ?? $Request.Body.ID + $MessageCopyForSentAsEnabled = $Request.Query.MessageCopyForSentAsEnabled ?? $Request.Body.MessageCopyForSentAsEnabled + $MessageCopyForSentAsEnabled = [System.Convert]::ToBoolean($MessageCopyForSentAsEnabled) + Try { - $MessageCopyForSentAsEnabled = if ($request.query.MessageCopyForSentAsEnabled -eq 'false') { 'false' } else { 'true' } - $MessageResult = Set-CIPPMessageCopy -userid $Request.query.id -tenantFilter $Request.query.TenantFilter -APIName $APINAME -Headers $Request.Headers -MessageCopyForSentAsEnabled $MessageCopyForSentAsEnabled - $Results = [pscustomobject]@{'Results' = "$MessageResult" } + $Result = Set-CIPPMessageCopy -userid $UserID -tenantFilter $TenantFilter -APIName $APIName -Headers $Headers -MessageCopyForSentAsEnabled $MessageCopyForSentAsEnabled + $StatusCode = [HttpStatusCode]::OK } catch { - $Results = [pscustomobject]@{'Results' = "set MessageCopyForSentAsEnabled to $MessageCopyForSentAsEnabled failed - $($_.Exception.Message)" } + $Result = "$($_.Exception.Message)" + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Results + StatusCode = $StatusCode + Body = @{ 'Results' = $Result } }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecSetMailboxLocale.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecSetMailboxLocale.ps1 index f7d1c12ba762..5d7d9e1c2392 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecSetMailboxLocale.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecSetMailboxLocale.ps1 @@ -11,20 +11,26 @@ Function Invoke-ExecSetMailboxLocale { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $Tenant = $Request.body.TenantFilter - $User = $Request.Headers - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -Headers $User -API $APIName -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + # Interact with query parameters or the body of the request. + $Tenant = $Request.Body.tenantFilter + $User = $Request.Body.user + $Locale = $Request.Body.locale + try { + $Result = Set-CippMailboxLocale -username $User -locale $Locale -tenantFilter $Tenant -APIName $APIName -Headers $Headers + $StatusCode = [HttpStatusCode]::OK + } catch { + $Result = "$($_.Exception.Message)" + $StatusCode = [HttpStatusCode]::InternalServerError + } - # Interact with query parameters or the body of the request. - $Results = Set-CippMailboxLocale -username $Request.Body.user -locale $Request.body.locale -tenantFilter $Tenant -APIName $APINAME -Headers $User # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = @{ Results = $Results } + StatusCode = $StatusCode + Body = @{ Results = $Result } }) } diff --git a/Modules/CIPPCore/Public/Set-CIPPMailboxLocale.ps1 b/Modules/CIPPCore/Public/Set-CIPPMailboxLocale.ps1 index 42f922e7891a..5d3fde2bbdf1 100644 --- a/Modules/CIPPCore/Public/Set-CIPPMailboxLocale.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPMailboxLocale.ps1 @@ -14,11 +14,13 @@ function Set-CippMailboxLocale { Language = $locale LocalizeDefaultFolderName = $true } -Anchor $username - Write-LogMessage -headers $Headers -API $APIName -message "set locale for $($username) to a $locale" -Sev 'Info' -tenant $TenantFilter - return "set locale for $($username) to a $locale" + $Result = "Set locale for $($username) to a $locale" + Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Info' -tenant $TenantFilter + return $Result } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers -API $APIName -message "Could not set locale for $($username). Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - return "Could not set locale for $username. Error: $($ErrorMessage.NormalizedError)" + $Result = "Could not set locale for $($username). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + throw $Result } } diff --git a/Modules/CIPPCore/Public/Set-CIPPMessageCopy.ps1 b/Modules/CIPPCore/Public/Set-CIPPMessageCopy.ps1 index 8f3e6fe17c33..512d56a75257 100644 --- a/Modules/CIPPCore/Public/Set-CIPPMessageCopy.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPMessageCopy.ps1 @@ -2,18 +2,20 @@ function Set-CIPPMessageCopy { [CmdletBinding()] param ( $userid, - $MessageCopyForSentAsEnabled, + [bool]$MessageCopyForSentAsEnabled, $TenantFilter, $APIName = 'Manage OneDrive Access', $Headers ) Try { - New-ExoRequest -tenantid $TenantFilter -cmdlet 'Set-Mailbox' -cmdParams @{Identity = $userid; MessageCopyForSentAsEnabled = $MessageCopyForSentAsEnabled } - Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenantfilter) -message "Successfully set MessageCopyForSentAsEnabled as $MessageCopyForSentAsEnabled on $($userid)." -Sev 'Info' - return "Successfully set MessageCopyForSentAsEnabled as $MessageCopyForSentAsEnabled on $($userid)." + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Set-Mailbox' -cmdParams @{Identity = $userid; MessageCopyForSentAsEnabled = $MessageCopyForSentAsEnabled } + $Result = "Successfully set MessageCopyForSentAsEnabled as $MessageCopyForSentAsEnabled on $($userid)." + Write-LogMessage -headers $Headers -API $APIName -tenant $($TenantFilter) -message $Result -Sev 'Info' + return $Result } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenantfilter) -message "set MessageCopyForSentAsEnabled to $MessageCopyForSentAsEnabled failed: $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage - return "set MessageCopyForSentAsEnabled to $MessageCopyForSentAsEnabled failed - $($ErrorMessage.NormalizedError)" + $Result = "Failed to set MessageCopyForSentAsEnabled to $MessageCopyForSentAsEnabled - $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $($TenantFilter) -message $Result -Sev 'Error' -LogData $ErrorMessage + throw $Result } } From 12d7e71c1de60ccc06c168148c37eccfeb9488fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sun, 23 Feb 2025 20:55:04 +0100 Subject: [PATCH 047/167] Refactor API functions to enhance parameter handling and improve logging consistency --- .../Users/Invoke-ExecCreateTAP.ps1 | 17 +++++++++----- .../Users/Invoke-ExecResetMFA.ps1 | 22 +++++++++---------- Modules/CIPPCore/Public/Invoke-RemoveUser.ps1 | 3 +-- Modules/CIPPCore/Public/New-CIPPTAP.ps1 | 16 ++++++-------- .../CIPPCore/Public/Set-CIPPHideFromGAL.ps1 | 10 +++++---- 5 files changed, 36 insertions(+), 32 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecCreateTAP.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecCreateTAP.ps1 index 4fc76d7300a6..c4e205aaa480 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecCreateTAP.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecCreateTAP.ps1 @@ -11,20 +11,25 @@ Function Invoke-ExecCreateTAP { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $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. + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $UserID = $Request.Query.ID ?? $Request.Body.ID + try { - $TAP = New-CIPPTAP -userid $Request.query.ID -TenantFilter $Request.query.tenantfilter -APIName $APINAME -Headers $Request.Headers - $Results = [pscustomobject]@{'Results' = $TAP } + $Result = New-CIPPTAP -userid $UserID -TenantFilter $TenantFilter -APIName $APIName -Headers $Headers + $StatusCode = [HttpStatusCode]::OK } catch { - $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" } + $Result = "$($_.Exception.Message)" + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Results + StatusCode = $StatusCode + Body = @{'Results' = $Result } }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetMFA.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetMFA.ps1 index f7ecd21d59e9..4cb4c25db418 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetMFA.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetMFA.ps1 @@ -11,25 +11,25 @@ Function Invoke-ExecResetMFA { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $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. - $TenantFilter = $Request.Query.TenantFilter - $UserID = $Request.Query.ID + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $UserID = $Request.Query.ID ?? $Request.Body.ID try { - - $Body = @{ - Results = Remove-CIPPUserMFA -UserPrincipalName $UserID -TenantFilter $TenantFilter -Headers $Request.Headers - } + $Result = Remove-CIPPUserMFA -UserPrincipalName $UserID -TenantFilter $TenantFilter -Headers $Headers + if ($Result -match 'Failed') { throw $Result } + $StatusCode = [HttpStatusCode]::OK } catch { - $Body = [pscustomobject]@{'Results' = "Failed to reset MFA methods for $($Request.Query.ID): $(Get-NormalizedError -message $_.Exception.Message)" } - Write-LogMessage -headers $Request.Headers -API $APINAME -message "Failed to reset MFA for user $($Request.Query.ID): $($_.Exception.Message)" -Sev 'Error' -LogData (Get-CippException -Exception $_) + $Result = "$($_.Exception.Message)" + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Body + StatusCode = $StatusCode + Body = @{ 'Results' = $Result } }) } diff --git a/Modules/CIPPCore/Public/Invoke-RemoveUser.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveUser.ps1 index 816bf4c5bfab..dc21f41c14ac 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveUser.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveUser.ps1 @@ -32,10 +32,9 @@ Function Invoke-RemoveUser { $StatusCode = [HttpStatusCode]::InternalServerError } - $Body = [pscustomobject]@{ 'Results' = $Result } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = $StatusCode - Body = $Body + Body = @{ 'Results' = $Result } }) } diff --git a/Modules/CIPPCore/Public/New-CIPPTAP.ps1 b/Modules/CIPPCore/Public/New-CIPPTAP.ps1 index 90df35f9d05c..3f500f41a30d 100644 --- a/Modules/CIPPCore/Public/New-CIPPTAP.ps1 +++ b/Modules/CIPPCore/Public/New-CIPPTAP.ps1 @@ -7,21 +7,19 @@ function New-CIPPTAP { $Headers ) - try { $GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($userid)/authentication/temporaryAccessPassMethods" -tenantid $TenantFilter -type POST -body '{}' -verbose Write-LogMessage -headers $Headers -API $APIName -message "Created Temporary Access Password (TAP) for $userid" -Sev 'Info' -tenant $TenantFilter - return [pscustomobject]@{ resultText = "The TAP for this user is $($GraphRequest.temporaryAccessPass) - This TAP is usable for the next $($GraphRequest.LifetimeInMinutes) minutes" - copyField = $($GraphRequest.temporaryAccessPass) - state = 'success' - } + $Results = [System.Collections.Generic.List[string]]::new() + $Results.Add("The TAP for this user is $($GraphRequest.temporaryAccessPass) - This TAP is usable for the next $($GraphRequest.LifetimeInMinutes) minutes") + $Results.Add("$($GraphRequest.temporaryAccessPass)") + return $Results } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers -API $APIName -message "Failed to created TAP for $($userid): $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - Return [pscustomobject]@{ resultText = "Failed to create TAP: $($ErrorMessage.NormalizedError)" - state = 'error' - } + $Result = "Failed to create Temporary Access Password (TAP) for $($userid): $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + throw @{ Results = $Result } } diff --git a/Modules/CIPPCore/Public/Set-CIPPHideFromGAL.ps1 b/Modules/CIPPCore/Public/Set-CIPPHideFromGAL.ps1 index 5ce6cf6726be..23d8bc8e8462 100644 --- a/Modules/CIPPCore/Public/Set-CIPPHideFromGAL.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPHideFromGAL.ps1 @@ -10,11 +10,13 @@ function Set-CIPPHideFromGAL { $Text = if ($HideFromGAL) { 'hidden' } else { 'unhidden' } try { $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Set-Mailbox' -cmdParams @{Identity = $UserId ; HiddenFromAddressListsEnabled = $HideFromGAL } - Write-LogMessage -headers $Headers -API $APIName -tenant $($TenantFilter) -message "$($UserId) $Text from GAL" -Sev Info - return "Successfully $Text $($UserId) from GAL." + $Result = "Successfully $Text $($UserId) from GAL." + Write-LogMessage -headers $Headers -API $APIName -tenant $($TenantFilter) -message $Result -Sev Info + return $Result } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers -API $APIName -message "Could not hide $($UserId) from address list. Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - return "Could not hide $($UserId) from address list. Error: $($ErrorMessage.NormalizedError)" + $Result = "Failed to hide $($UserId) from GAL. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + return $Result } } From 83e55d46482b7bbcd87eef5086e2d51421e2005d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sun, 23 Feb 2025 21:12:13 +0100 Subject: [PATCH 048/167] Refactor email filter functions to improve parameter handling and logging consistency --- .../Invoke-EditAntiPhishingFilter.ps1 | 38 ++++++++++--------- .../Invoke-EditMalwareFilter.ps1 | 38 ++++++++++--------- .../Invoke-EditSafeAttachmentsFilter.ps1 | 38 ++++++++++--------- .../Invoke-EditSafeLinksFilter.ps1 | 36 +++++++++--------- 4 files changed, 79 insertions(+), 71 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditAntiPhishingFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditAntiPhishingFilter.ps1 index feaa27471516..86f787e74d1a 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditAntiPhishingFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditAntiPhishingFilter.ps1 @@ -9,24 +9,24 @@ function Invoke-EditAntiPhishingFilter { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + $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. - $TenantFilter = $Request.Query.TenantFilter + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName + $State = $Request.Query.State ?? $Request.Body.State try { $ExoRequestParam = @{ - tenantid = $TenantFilter - cmdParams = @{ - Identity = $Request.query.RuleName + tenantid = $TenantFilter + cmdParams = @{ + Identity = $RuleName } - useSystemmailbox = $true + useSystemMailbox = $true } - switch ($Request.query.State) { + switch ($State) { 'Enable' { $ExoRequestParam.Add('cmdlet', 'Enable-AntiPhishRule') } @@ -37,19 +37,21 @@ function Invoke-EditAntiPhishingFilter { throw 'Invalid state' } } - New-ExoRequest @ExoRequestParam + $null = New-ExoRequest @ExoRequestParam - $Result = "Sucessfully set Anti-Phishing rule $($Request.query.RuleName) to $($Request.query.State)" - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev Info + $Result = "Successfully set Anti-Phishing rule $RuleName to $State" + Write-LogMessage -headers $Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev Info + $StatusCode = [HttpStatusCode]::OK } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - $Result = "Failed setting Anti-Phishing rule $($Request.query.RuleName) to $($request.query.State). Error: $ErrorMessage" - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev 'Error' + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed setting Anti-Phishing rule $RuleName to $State. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK + StatusCode = $StatusCode Body = @{Results = $Result } - }) + }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditMalwareFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditMalwareFilter.ps1 index 315596cb252e..fb1943714bf4 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditMalwareFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditMalwareFilter.ps1 @@ -9,24 +9,24 @@ function Invoke-EditMalwareFilter { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + $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. - $TenantFilter = $Request.Query.TenantFilter + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName + $State = $Request.Query.State ?? $Request.Body.State try { $ExoRequestParam = @{ - tenantid = $TenantFilter - cmdParams = @{ - Identity = $Request.query.RuleName + tenantid = $TenantFilter + cmdParams = @{ + Identity = $RuleName } - useSystemmailbox = $true + useSystemMailbox = $true } - switch ($Request.query.State) { + switch ($State) { 'Enable' { $ExoRequestParam.Add('cmdlet', 'Enable-MalwareFilterRule') } @@ -37,19 +37,21 @@ function Invoke-EditMalwareFilter { throw 'Invalid state' } } - New-ExoRequest @ExoRequestParam + $null = New-ExoRequest @ExoRequestParam - $Result = "Sucessfully set Malware Filter rule $($Request.query.RuleName) to $($Request.query.State)" - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev Info + $Result = "Successfully set Malware Filter rule $($RuleName) to $($State)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev Info + $StatusCode = [HttpStatusCode]::OK } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - $Result = "Failed setting Malware Filter rule $($Request.query.RuleName) to $($request.query.State). Error: $ErrorMessage" - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev 'Error' + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed setting Malware Filter rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK + StatusCode = $StatusCode Body = @{Results = $Result } - }) + }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeAttachmentsFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeAttachmentsFilter.ps1 index b552059cabf8..a6eae5585946 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeAttachmentsFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeAttachmentsFilter.ps1 @@ -9,24 +9,24 @@ function Invoke-EditSafeAttachmentsFilter { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + $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. - $TenantFilter = $Request.Query.TenantFilter + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName + $State = $Request.Query.State ?? $Request.Body.State try { $ExoRequestParam = @{ - tenantid = $TenantFilter - cmdParams = @{ - Identity = $Request.query.RuleName + tenantid = $TenantFilter + cmdParams = @{ + Identity = $RuleName } - useSystemmailbox = $true + useSystemMailbox = $true } - switch ($Request.query.State) { + switch ($State) { 'Enable' { $ExoRequestParam.Add('cmdlet', 'Enable-SafeAttachmentRule') } @@ -37,19 +37,21 @@ function Invoke-EditSafeAttachmentsFilter { throw 'Invalid state' } } - New-ExoRequest @ExoRequestParam + $null = New-ExoRequest @ExoRequestParam - $Result = "Sucessfully set SafeAttachment rule $($Request.query.RuleName) to $($Request.query.State)" - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev Info + $Result = "Successfully set SafeAttachment rule $($RuleName) to $($State)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - $Result = "Failed setting SafeAttachment rule $($Request.query.RuleName) to $($request.query.State). Error: $ErrorMessage" - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev 'Error' + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed setting SafeAttachment rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK + StatusCode = $StatusCode Body = @{Results = $Result } - }) + }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeLinksFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeLinksFilter.ps1 index 9d1663070e2e..aa3f3e461175 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeLinksFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeLinksFilter.ps1 @@ -9,24 +9,24 @@ function Invoke-EditSafeLinksFilter { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + $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. - $TenantFilter = $Request.Query.TenantFilter + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName + $State = $Request.Query.State ?? $Request.Body.State try { $ExoRequestParam = @{ - tenantid = $TenantFilter - cmdParams = @{ - Identity = $Request.query.RuleName + tenantid = $TenantFilter + cmdParams = @{ + Identity = $RuleName } useSystemmailbox = $true } - switch ($Request.query.State) { + switch ($State) { 'Enable' { $ExoRequestParam.Add('cmdlet', 'Enable-SafeLinksRule') } @@ -37,19 +37,21 @@ function Invoke-EditSafeLinksFilter { throw 'Invalid state' } } - New-ExoRequest @ExoRequestParam + $null = New-ExoRequest @ExoRequestParam - $Result = "Sucessfully set SafeLinks rule $($Request.query.RuleName) to $($Request.query.State)" - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev Info + $Result = "Successfully set SafeLinks rule $($RuleName) to $($State)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev Info + $StatusCode = [HttpStatusCode]::OK } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - $Result = "Failed setting SafeLinks rule $($Request.query.RuleName) to $($request.query.State). Error: $ErrorMessage" - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev 'Error' + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed setting SafeLinks rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK + StatusCode = $StatusCode Body = @{Results = $Result } - }) + }) } From fef5710d20eb09d8fa9b85628634670e4c896a2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sun, 23 Feb 2025 21:13:13 +0100 Subject: [PATCH 049/167] typo --- .../Email-Exchange/Invoke-EditSafeLinksFilter.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeLinksFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeLinksFilter.ps1 index aa3f3e461175..89141c9f413e 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeLinksFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeLinksFilter.ps1 @@ -23,7 +23,7 @@ function Invoke-EditSafeLinksFilter { cmdParams = @{ Identity = $RuleName } - useSystemmailbox = $true + useSystemMailbox = $true } switch ($State) { From e246aac9bcd1afbd83357511a37c777cd3988c93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sun, 23 Feb 2025 21:29:24 +0100 Subject: [PATCH 050/167] Refactor API functions to improve header handling, error messaging, and logging consistency --- .../Endpoint/MEM/Invoke-AddIntuneTemplate.ps1 | 3 +- .../Endpoint/MEM/Invoke-ExecAssignPolicy.ps1 | 28 ++++++++++--------- .../MEM/Invoke-ExecGetRecoveryKey.ps1 | 25 ++++++++--------- .../CIPPCore/Public/Get-CIPPBitlockerKey.ps1 | 9 +++--- 4 files changed, 33 insertions(+), 32 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddIntuneTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddIntuneTemplate.ps1 index 24c00cf0adff..d85863fbbe41 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddIntuneTemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddIntuneTemplate.ps1 @@ -11,7 +11,8 @@ Function Invoke-AddIntuneTemplate { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' $GUID = (New-Guid).GUID try { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecAssignPolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecAssignPolicy.ps1 index 6c1b711d7c4d..e4db5b138966 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecAssignPolicy.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecAssignPolicy.ps1 @@ -11,31 +11,33 @@ Function Invoke-ExecAssignPolicy { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - $Tenant = $request.body.tenantfilter - $ID = $request.body.id - $displayname = $request.body.Displayname - $AssignTo = if ($request.body.Assignto -ne 'on') { $request.body.Assignto } + # Interact with the body of the request + $TenantFilter = $Request.Body.tenantFilter + $ID = $request.Body.ID + $Type = $Request.Body.Type + $AssignTo = $Request.Body.AssignTo + + $AssignTo = if ($AssignTo -ne 'on') { $AssignTo } $results = try { if ($AssignTo) { - $assign = Set-CIPPAssignedPolicy -PolicyId $ID -TenantFilter $tenant -GroupName $AssignTo -Type $Request.body.Type -Headers $Request.Headers - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($Tenant) -message "Assigned policy $($Displayname) to $AssignTo" -Sev 'Info' + $null = Set-CIPPAssignedPolicy -PolicyId $ID -TenantFilter $TenantFilter -GroupName $AssignTo -Type $Type -Headers $Headers } - "Successfully edited policy for $($Tenant)" + "Successfully edited policy for $($TenantFilter)" + $StatusCode = [HttpStatusCode]::OK } catch { - "Failed to add policy for $($Tenant): $($_.Exception.Message)" - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($Tenant) -message "Failed editing policy $($Displayname). Error:$($_.Exception.Message)" -Sev 'Error' - continue + "Failed to add policy for $($TenantFilter): $($_.Exception.Message)" + $StatusCode = [HttpStatusCode]::InternalServerError } - $body = [pscustomobject]@{'Results' = $results } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body + StatusCode = $StatusCode + Body = @{Results = $results } }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecGetRecoveryKey.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecGetRecoveryKey.ps1 index 9d7eed11b7fb..2ab268e9a852 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecGetRecoveryKey.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecGetRecoveryKey.ps1 @@ -11,28 +11,25 @@ Function Invoke-ExecGetRecoveryKey { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + $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. - $TenantFilter = $Request.Query.TenantFilter - try { - $GraphRequest = Get-CIPPBitlockerKey -device $Request.query.GUID -tenantFilter $TenantFilter -APIName $APINAME -Headers $Request.Headers - $Body = [pscustomobject]@{'Results' = $GraphRequest } + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $GUID = $Request.Query.GUID ?? $Request.Body.GUID + try { + $Result = Get-CIPPBitLockerKey -device $GUID -tenantFilter $TenantFilter -APIName $APIName -Headers $Headers + $StatusCode = [HttpStatusCode]::OK } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - $Body = [pscustomobject]@{'Results' = "Failed. $ErrorMessage" } - + $Result = $_.Exception.Message + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Body + StatusCode = $StatusCode + Body = @{Results = $Result } }) } diff --git a/Modules/CIPPCore/Public/Get-CIPPBitlockerKey.ps1 b/Modules/CIPPCore/Public/Get-CIPPBitlockerKey.ps1 index b7d8b1646468..291d5b06f63e 100644 --- a/Modules/CIPPCore/Public/Get-CIPPBitlockerKey.ps1 +++ b/Modules/CIPPCore/Public/Get-CIPPBitlockerKey.ps1 @@ -4,7 +4,7 @@ function Get-CIPPBitlockerKey { param ( $device, $TenantFilter, - $APIName = 'Get Bitlocker key', + $APIName = 'Get BitLocker key', $Headers ) @@ -14,8 +14,9 @@ function Get-CIPPBitlockerKey { } return $GraphRequest } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -headers $Headers -API $APIName -message "Could not retrieve bitlocker recovery key for $($device)" -Sev 'Error' -tenant $TenantFilter -LogData (Get-CippException -Exception $_) - return "Could not retrieve bitlocker recovery key for $($device). Error: $ErrorMessage" + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Could not retrieve BitLocker recovery key for $($device). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + throw $Result } } From ea27a051d1cd1ad51b896aa9fc749d424e1ad23b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sun, 23 Feb 2025 22:23:52 +0100 Subject: [PATCH 051/167] Refactor API functions to enhance parameter handling, logging consistency, and error messaging --- .../Invoke-ExecRemoveMailboxRule.ps1 | 9 +++-- .../Users/Invoke-ExecDismissRiskyUser.ps1 | 39 ++++++++++--------- .../Alerts/Invoke-RemoveQueuedAlert.ps1 | 26 ++++++++----- .../Conditional/Invoke-EditCAPolicy.ps1 | 33 +++++++++------- 4 files changed, 61 insertions(+), 46 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecRemoveMailboxRule.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecRemoveMailboxRule.ps1 index 4ae271d4bf4d..e06da5bc17b2 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecRemoveMailboxRule.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecRemoveMailboxRule.ps1 @@ -11,19 +11,20 @@ Function Invoke-ExecRemoveMailboxRule { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -Headers $Headers -API $APIName -tenant $TenantFilter -message 'Accessed this API' -Sev 'Debug' + + # Interact with the query or body of the request $TenantFilter = $Request.Query.TenantFilter ?? $Request.Query.TenantFilter $RuleName = $Request.Query.ruleName ?? $Request.Body.ruleName $RuleId = $Request.Query.ruleId ?? $Request.Body.ruleId $Username = $Request.Query.userPrincipalName ?? $Request.Body.userPrincipalName - $Headers = $Request.Headers - Write-LogMessage -Headers $Headers -API $APIName -tenant $TenantFilter -message 'Accessed this API' -Sev 'Debug' - # Remove the rule $Results = Remove-CIPPMailboxRule -username $Username -TenantFilter $TenantFilter -APIName $APIName -Headers $Headers -RuleId $RuleId -RuleName $RuleName if ($Results -like '*Could not delete*') { - $StatusCode = [HttpStatusCode]::Forbidden + $StatusCode = [HttpStatusCode]::InternalServerError } else { $StatusCode = [HttpStatusCode]::OK } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDismissRiskyUser.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDismissRiskyUser.ps1 index 53cdc664fa6c..d2b0e4efce53 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDismissRiskyUser.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDismissRiskyUser.ps1 @@ -9,36 +9,39 @@ function Invoke-ExecDismissRiskyUser { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - Write-Host 'PowerShell HTTP trigger function processed a request.' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - $TenantFilter = $Request.Query.tenantfilter - $SuspectUser = $Request.Query.userid - $userDisplayName = $Request.Query.userDisplayName + # Interact with the query or body of the request + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $SuspectUser = $Request.Query.userId ?? $Request.Body.userId + $userDisplayName = $Request.Query.userDisplayName ?? $Request.Body.userDisplayName $GraphRequest = @{ - 'uri' = 'https://graph.microsoft.com/beta/riskyUsers/dismiss' - 'tenantid' = $TenantFilter - 'type' = 'POST' - 'contentType' = 'application/json; charset=utf-8' - 'body' = @{ + 'uri' = 'https://graph.microsoft.com/beta/riskyUsers/dismiss' + 'tenantid' = $TenantFilter + 'type' = 'POST' + 'contentType' = 'application/json; charset=utf-8' + 'body' = @{ 'userIds' = @($SuspectUser) } | ConvertTo-Json } try { $GraphResults = New-GraphPostRequest @GraphRequest - Write-LogMessage -API 'DismissRiskyUser' -tenant $TenantFilter -message "Dismissed user risk for $userDisplayName" -sev 'Info' - - $ResponseBody = [pscustomobject]@{ 'Results' = "Successfully dismissed User Risk for user $userDisplayName. $GraphResults" } + Write-LogMessage -API $APIName -tenant $TenantFilter -message "Dismissed user risk for $userDisplayName" -sev 'Info' + $Result = "Successfully dismissed User Risk for user $userDisplayName. $GraphResults" + $StatusCode = [HttpStatusCode]::OK } catch { - $ResponseBody = [pscustomobject]@{ 'Results' = "Failed to execute dismissal. $($_.Exception.Message)" } - Write-LogMessage -API 'DismissRiskyUser' -tenant $TenantFilter -message "Failed to dismiss user risk for $userDisplayName" -sev 'Error' + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed to dismiss user risk for $userDisplayName. $($ErrorMessage.NormalizedError)" + Write-LogMessage -API $APIName -tenant $TenantFilter -message $Result -sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $ResponseBody - }) + StatusCode = $StatusCode + Body = @{ 'Results' = $Result } + }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-RemoveQueuedAlert.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-RemoveQueuedAlert.ps1 index 2442dbcf934a..1ee3c7dcb788 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-RemoveQueuedAlert.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-RemoveQueuedAlert.ps1 @@ -11,32 +11,38 @@ Function Invoke-RemoveQueuedAlert { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - if ($Request.query.EventType -eq 'Audit log Alert') { + # Interact with the query or body of the request + $EventType = $Request.Query.EventType ?? $Request.Body.EventType + $ID = $Request.Query.ID ?? $Request.Body.ID + + if ($EventType -eq 'Audit log Alert') { $Table = 'WebhookRules' } else { $Table = 'ScheduledTasks' } $Table = Get-CIPPTable -TableName $Table - $ID = $request.query.id try { $Filter = "RowKey eq '{0}'" -f $ID $Alert = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey Remove-AzDataTableEntity -Force @Table -Entity $Alert - Write-LogMessage -headers $Request.Headers -API $APINAME -message "Removed application queue for $ID." -Sev 'Info' - - $body = [pscustomobject]@{'Results' = 'Successfully removed from queue.' } + $Result = "Successfully removed alert $ID from queue" + Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK } catch { - Write-LogMessage -headers $Request.Headers -API $APINAME -message "Failed to remove from queue $ID. $($_.Exception.Message)" -Sev 'Error' - $body = [pscustomobject]@{'Results' = "Failed to remove alert from queue $($_.Exception.Message)" } + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed to remove alert from queue $ID. $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body + StatusCode = $StatusCode + Body = @{ 'Results' = $Result } }) 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 1e8d5662663a..e8d3d5692a54 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 @@ -11,26 +11,31 @@ Function Invoke-EditCAPolicy { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - $Tenant = $request.query.tenantFilter - $ID = $request.query.guid - $results = try { - $EditBody = "{`"state`": `"$($request.query.state)`"}" - $Request = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta//identity/conditionalAccess/policies/$($id)" -tenantid $tenant -type PATCH -body $EditBody -asapp $true - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($Tenant) -message "Edited CA policy: $($ID)" -Sev 'Info' - "Successfully edited CA policy: $($ID)" + # Interact with the request + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $ID = $Request.Query.GUID ?? $Request.Body.GUID + $State = $Request.Query.State ?? $Request.Body.State + + try { + $EditBody = "{`"state`": `"$($State)`"}" + $Request = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta//identity/conditionalAccess/policies/$($ID)" -tenantid $TenantFilter -type PATCH -body $EditBody -asapp $true + $Result = "Successfully set CA policy $($ID) to $($State)" + Write-LogMessage -headers $Headers -API $APIName -tenant $($TenantFilter) -message $Result -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK } catch { - "Failed to add CA policy: $($_.Exception.Message)" - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($Tenant) -message "Failed editing CA policy $($ID). Error: $($_.Exception.Message)" -Sev 'Error' + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed to set CA policy $($ID) to $($State): $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $($TenantFilter) -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } - $body = [pscustomobject]@{'Results' = $results } - # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body + StatusCode = $StatusCode + Body = @{ 'Results' = $Result } }) } From 6bd7c23887bc913ffa6fcc0c6a0961433713b8a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 24 Feb 2025 16:52:23 +0100 Subject: [PATCH 052/167] fix dumb --- .../CIPP/Settings/Invoke-ExecCPVPermissions.ps1 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCPVPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCPVPermissions.ps1 index ae464286d3cc..0384b3e3c350 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCPVPermissions.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCPVPermissions.ps1 @@ -11,8 +11,9 @@ Function Invoke-ExecCPVPermissions { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - $TenantFilter = $TenantFilter + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $TenantFilter = $Request.Body.tenantFilter $Tenant = Get-Tenants -IncludeAll | Where-Object -Property customerId -EQ $TenantFilter | Select-Object -First 1 From ce0fdd4ab99916e06311867201844092736fac9e Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 24 Feb 2025 17:20:47 +0100 Subject: [PATCH 053/167] remove += --- .../Invoke-CIPPStandardQuarantineRequestAlert.ps1 | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 index 3040ef1f155e..1b0b39848081 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 @@ -52,9 +52,7 @@ function Invoke-CIPPStandardQuarantineRequestAlert { if ($CurrentState.Name -eq $PolicyName) { try { - $cmdparams += @{ - 'Identity' = $PolicyName - } + $cmdparams['Identity'] = $PolicyName New-ExoRequest -TenantId $Tenant -cmdlet 'Set-ProtectionAlert' -Compliance -cmdparams $cmdparams -UseSystemMailbox $true Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully configured Quarantine Request Alert' -sev Info } catch { @@ -63,10 +61,9 @@ function Invoke-CIPPStandardQuarantineRequestAlert { } } else { try { - $cmdparams += @{ - 'Name' = $PolicyName - 'ThreatType' = 'Activity' - } + $cmdparams['name'] = $PolicyName + $cmdparams['ThreatType'] = 'Activity' + New-ExoRequest -TenantId $Tenant -cmdlet 'New-ProtectionAlert' -Compliance -cmdparams $cmdparams -UseSystemMailbox $true Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully created Quarantine Request Alert' -sev Info } catch { From b962e176c71a7fb07d6697a675ad4bdc2c47d9e6 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 24 Feb 2025 18:06:11 +0100 Subject: [PATCH 054/167] fixes assignment policy += usage. --- .../Public/Set-CIPPAssignedPolicy.ps1 | 85 ++++++++++--------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 b/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 index 9b1714c3a6fe..5386bd8dff9a 100644 --- a/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 @@ -10,96 +10,105 @@ function Set-CIPPAssignedPolicy { $APIName = 'Assign Policy', $Headers ) - if (!$PlatformType) { $PlatformType = 'deviceManagement' } - try { - $assignmentsObject = @() + if (!$PlatformType) { + $PlatformType = 'deviceManagement' + } - $assignmentsObject += switch ($GroupName) { + try { + $assignmentsList = New-Object System.Collections.Generic.List[System.Object] + switch ($GroupName) { 'allLicensedUsers' { - @{ - target = @{ - '@odata.type' = '#microsoft.graph.allLicensedUsersAssignmentTarget' + $assignmentsList.Add( + @{ + target = @{ + '@odata.type' = '#microsoft.graph.allLicensedUsersAssignmentTarget' + } } - } - break + ) } 'AllDevices' { - @{ - target = @{ - '@odata.type' = '#microsoft.graph.allDevicesAssignmentTarget' + $assignmentsList.Add( + @{ + target = @{ + '@odata.type' = '#microsoft.graph.allDevicesAssignmentTarget' + } } - } - break + ) } 'AllDevicesAndUsers' { - @( + $assignmentsList.Add( @{ target = @{ '@odata.type' = '#microsoft.graph.allDevicesAssignmentTarget' } - }, + } + ) + $assignmentsList.Add( @{ target = @{ '@odata.type' = '#microsoft.graph.allLicensedUsersAssignmentTarget' } } ) - break } default { Write-Host "We're supposed to assign a custom group. The group is $GroupName" $GroupNames = $GroupName.Split(',') - $GroupIds = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/groups?$select=id,displayName&$top=999' -tenantid $TenantFilter | ForEach-Object { - $Group = $_ + $GroupIds = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/groups?$select=id,displayName&$top=999' -tenantid $TenantFilter | + ForEach-Object { foreach ($SingleName in $GroupNames) { if ($_.displayName -like $SingleName) { $_.id } } } - $GroupIds | ForEach-Object { - @{ - target = @{ - '@odata.type' = '#microsoft.graph.groupAssignmentTarget' - groupId = $_ + foreach ($gid in $GroupIds) { + $assignmentsList.Add( + @{ + target = @{ + '@odata.type' = '#microsoft.graph.groupAssignmentTarget' + groupId = $gid + } } - } + ) } } } - - # Handle excludeGroup if ($excludeGroup) { $ExcludeGroupNames = $excludeGroup.Split(',') - $ExcludeGroupIds = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/groups?$select=id,displayName&$top=999' -tenantid $TenantFilter | ForEach-Object { - $Group = $_ + $ExcludeGroupIds = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/groups?$select=id,displayName&$top=999' -tenantid $TenantFilter | + ForEach-Object { foreach ($SingleName in $ExcludeGroupNames) { if ($_.displayName -like $SingleName) { $_.id } } } - $ExcludeGroupIds | ForEach-Object { - $assignmentsObject += @{ - target = @{ - '@odata.type' = '#microsoft.graph.exclusionGroupAssignmentTarget' - groupId = $_ + + foreach ($egid in $ExcludeGroupIds) { + $assignmentsList.Add( + @{ + target = @{ + '@odata.type' = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = $egid + } } - } + ) } } $assignmentsObject = [PSCustomObject]@{ - assignments = $assignmentsObject + assignments = $assignmentsList } - $AssignJSON = ($assignmentsObject | ConvertTo-Json -Depth 10 -Compress) + $AssignJSON = $assignmentsObject | ConvertTo-Json -Depth 10 -Compress Write-Host "AssignJSON: $AssignJSON" if ($PSCmdlet.ShouldProcess($GroupName, "Assigning policy $PolicyId")) { Write-Host "https://graph.microsoft.com/beta/$($PlatformType)/$Type('$($PolicyId)')/assign" - $null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$($PlatformType)/$Type('$($PolicyId)')/assign" -tenantid $tenantFilter -type POST -body $AssignJSON + $null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$($PlatformType)/$Type('$($PolicyId)')/assign" -tenantid $TenantFilter -type POST -body $AssignJSON Write-LogMessage -headers $Headers -API $APIName -message "Assigned $GroupName and excluded $excludeGroup to Policy $PolicyId" -Sev 'Info' -tenant $TenantFilter } + } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message Write-LogMessage -headers $Headers -API $APIName -message "Failed to assign $GroupName to Policy $PolicyId, using Platform $PlatformType and $Type. The error is:$ErrorMessage" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage From 95332285b1175beff701c3a3667aad165570bc2e Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 24 Feb 2025 14:01:10 -0500 Subject: [PATCH 055/167] correct typo --- .../CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 index b00f525d0fef..635112cab398 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 @@ -55,7 +55,7 @@ function Invoke-CIPPStandardNudgeMFA { If ($Settings.remediate -eq $true) { $StateName = $Settings.state.Substring(0, 1).ToUpper() + $Settings.state.Substring(1) - if ($StatsIsCorrect -eq $false) { + if ($StateIsCorrect -eq $false) { try { $GraphRequest = @{ tenantid = $tenant From 0563f63e223ce6f041fbfcbf049f417281fdaf24 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 24 Feb 2025 14:10:36 -0500 Subject: [PATCH 056/167] add AppProtection type --- Modules/CIPPCore/Public/Tools/Import-CommunityTemplate.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/CIPPCore/Public/Tools/Import-CommunityTemplate.ps1 b/Modules/CIPPCore/Public/Tools/Import-CommunityTemplate.ps1 index 396757529a9f..8fd2c863d97c 100644 --- a/Modules/CIPPCore/Public/Tools/Import-CommunityTemplate.ps1 +++ b/Modules/CIPPCore/Public/Tools/Import-CommunityTemplate.ps1 @@ -76,6 +76,7 @@ function Import-CommunityTemplate { '*DriverUpdateProfiles*' { 'windowsDriverUpdateProfiles' } '*SettingsCatalog*' { 'Catalog' } '*configurationPolicies*' { 'Catalog' } + '*managedAppPolicies*' { 'AppProtection' } } $id = $Template.id $RawJson = $Template | Select-Object * -ExcludeProperty id, lastModifiedDateTime, 'assignments', '#microsoft*', '*@odata.navigationLink', '*@odata.associationLink', '*@odata.context', 'ScopeTagIds', 'supportsScopeTags', 'createdDateTime', '@odata.id', '@odata.editLink', 'lastModifiedDateTime@odata.type', 'roleScopeTagIds@odata.type', createdDateTime, 'createdDateTime@odata.type' From 7e8a67ae38b39fe21e55c169dab9daaf27c2f119 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 24 Feb 2025 14:58:17 -0500 Subject: [PATCH 057/167] Update Import-CommunityTemplate.ps1 --- Modules/CIPPCore/Public/Tools/Import-CommunityTemplate.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/CIPPCore/Public/Tools/Import-CommunityTemplate.ps1 b/Modules/CIPPCore/Public/Tools/Import-CommunityTemplate.ps1 index 8fd2c863d97c..5cfdcd6b5827 100644 --- a/Modules/CIPPCore/Public/Tools/Import-CommunityTemplate.ps1 +++ b/Modules/CIPPCore/Public/Tools/Import-CommunityTemplate.ps1 @@ -77,6 +77,7 @@ function Import-CommunityTemplate { '*SettingsCatalog*' { 'Catalog' } '*configurationPolicies*' { 'Catalog' } '*managedAppPolicies*' { 'AppProtection' } + '*deviceAppManagement*' { 'AppProtection' } } $id = $Template.id $RawJson = $Template | Select-Object * -ExcludeProperty id, lastModifiedDateTime, 'assignments', '#microsoft*', '*@odata.navigationLink', '*@odata.associationLink', '*@odata.context', 'ScopeTagIds', 'supportsScopeTags', 'createdDateTime', '@odata.id', '@odata.editLink', 'lastModifiedDateTime@odata.type', 'roleScopeTagIds@odata.type', createdDateTime, 'createdDateTime@odata.type' From 4de7484b6f34a891475bd90add5c2eb4d6239684 Mon Sep 17 00:00:00 2001 From: Esco Date: Tue, 25 Feb 2025 15:01:18 +0100 Subject: [PATCH 058/167] fix: added feature state check to PWdisplayAppInformationRequiredState --- ...nvoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 index 8ddea0115551..47eb6f68bf5c 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 @@ -32,7 +32,9 @@ function Invoke-CIPPStandardPWdisplayAppInformationRequiredState { ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'PWdisplayAppInformationRequiredState' $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator' -tenantid $Tenant - $StateIsCorrect = ($CurrentState.state -eq 'enabled') + $StateIsCorrect = ($CurrentState.state -eq 'enabled') -and + ($CurrentState.featureSettings.numberMatchingRequiredState.state -eq 'enabled') -and + ($CurrentState.featureSettings.displayAppInformationRequiredState.state -eq 'enabled') If ($Settings.remediate -eq $true) { if ($StateIsCorrect -eq $true) { From 2e655ce73db214e12991056e91551c7047902057 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 25 Feb 2025 10:01:31 -0500 Subject: [PATCH 059/167] fix config migration --- .../Webhooks/Push-AuditLogTenant.ps1 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenant.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenant.ps1 index 4276b516c810..b55e4bc85dbf 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenant.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenant.ps1 @@ -27,13 +27,13 @@ function Push-AuditLogTenant { $CIPPURL = $LegacyUrl } else { if (!$CippConfig) { - $CippConfig = @{ - PartitionKey = 'InstanceProperties' - RowKey = 'CIPPURL' - Value = [string]([System.Uri]$Request.Headers.'x-ms-original-url').Host - } - Add-AzDataTableEntity @ConfigTable -Entity $CippConfig -Force - $CIPPURL = 'https://{0}' -f $CippConfig.Value + $CippConfig = @{ + PartitionKey = 'InstanceProperties' + RowKey = 'CIPPURL' + Value = [string]([System.Uri]$Request.Headers.'x-ms-original-url').Host + } + Add-AzDataTableEntity @CippConfigTable -Entity $CippConfig -Force + $CIPPURL = 'https://{0}' -f $CippConfig.Value } else { $CIPPURL = 'https://{0}' -f $CippConfig.Value } } From 90cd66042a1c9ca4e0b9980914aa9ac87e986684 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 25 Feb 2025 11:20:00 -0500 Subject: [PATCH 060/167] chore: remove write-information --- Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1 b/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1 index 3bd121c0c1c6..4b4343a0296b 100644 --- a/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1 +++ b/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1 @@ -20,7 +20,7 @@ function Add-CIPPAzDataTableEntity { if ($_.Exception.ErrorCode -eq 'PropertyValueTooLarge' -or $_.Exception.ErrorCode -eq 'EntityTooLarge' -or $_.Exception.ErrorCode -eq 'RequestBodyTooLarge') { try { Write-Host 'Entity is too large. Splitting entity into multiple parts.' - Write-Information ($SingleEnt | ConvertTo-Json) + #Write-Information ($SingleEnt | ConvertTo-Json) $largePropertyNames = [System.Collections.Generic.List[string]]::new() $entitySize = 0 From 04145618fafc036557a1924d3c8d489f063b69b4 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 25 Feb 2025 11:20:35 -0500 Subject: [PATCH 061/167] fix: prevent error when deleting empty entity --- Modules/CIPPCore/Public/Test-CIPPRerun.ps1 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Modules/CIPPCore/Public/Test-CIPPRerun.ps1 b/Modules/CIPPCore/Public/Test-CIPPRerun.ps1 index a7f5ed0d676a..021678392573 100644 --- a/Modules/CIPPCore/Public/Test-CIPPRerun.ps1 +++ b/Modules/CIPPCore/Public/Test-CIPPRerun.ps1 @@ -22,7 +22,9 @@ function Test-CIPPRerun { $RerunData = Get-CIPPAzDataTableEntity @RerunTable -filter "PartitionKey eq '$($TenantFilter)' and RowKey eq '$($Type)_$($API)'" if ($ClearAll.IsPresent) { $AllRerunData = Get-CIPPAzDataTableEntity @RerunTable - Remove-AzDataTableEntity @RerunTable -Entity $AllRerunData -Force + if ($AllRerunData) { + Remove-AzDataTableEntity @RerunTable -Entity $AllRerunData -Force + } return $false } @@ -67,7 +69,7 @@ function Test-CIPPRerun { } catch { $ErrorMessage = Get-CippException -Exception $_ Write-Host "Could not detect if this is a rerun: $($ErrorMessage.NormalizedError)" - Write-LogMessage -headers $Headers -API $API -message "Could not detect if this is a rerun: $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage + Write-LogMessage -headers $Headers -API $API -message "Could not detect if this is a rerun: $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData (Get-CippException -Exception $_) return $false } } From 45e2089da5c3fe0e0244d2fd6d8456b567abc4dd Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 25 Feb 2025 11:30:57 -0500 Subject: [PATCH 062/167] error handling for auth method policy --- .../Standards/Invoke-CIPPStandardNudgeMFA.ps1 | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 index c217e2b1298e..1def2f369951 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 @@ -33,10 +33,15 @@ function Invoke-CIPPStandardNudgeMFA { # Get state value using null-coalescing operator $state = $Settings.state.value ?? $Settings.state - $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy' -tenantid $Tenant - $StateIsCorrect = ($CurrentState.registrationEnforcement.authenticationMethodsRegistrationCampaign.state -eq $state) -and + try { + $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy' -tenantid $Tenant + $StateIsCorrect = ($CurrentState.registrationEnforcement.authenticationMethodsRegistrationCampaign.state -eq $state) -and ($CurrentState.registrationEnforcement.authenticationMethodsRegistrationCampaign.snoozeDurationInDays -eq $Settings.snoozeDurationInDays) -and ($CurrentState.registrationEnforcement.authenticationMethodsRegistrationCampaign.enforceRegistrationAfterAllowedSnoozes -eq $true) + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Failed to get Authenticator App Nudge state, check your permissions and try again' -sev Error -LogData (Get-CippException -Exception $_) + Return + } if ($Settings.report -eq $true) { Add-CIPPBPAField -FieldName 'NudgeMFA' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant @@ -53,9 +58,7 @@ function Invoke-CIPPStandardNudgeMFA { Return } - - If ($Settings.remediate -eq $true) { - + if ($Settings.remediate -eq $true) { $StateName = $Settings.state.Substring(0, 1).ToUpper() + $Settings.state.Substring(1) if ($StateIsCorrect -eq $false) { try { @@ -71,6 +74,8 @@ function Invoke-CIPPStandardNudgeMFA { state = $state snoozeDurationInDays = $Settings.snoozeDurationInDays enforceRegistrationAfterAllowedSnoozes = $true + includeTargets = $CurrentState.registrationEnforcement.authenticationMethodsRegistrationCampaign.includeTargets + excludeTargets = $CurrentState.registrationEnforcement.authenticationMethodsRegistrationCampaign.excludeTargets } } } | ConvertTo-Json -Depth 10 -Compress @@ -92,4 +97,5 @@ function Invoke-CIPPStandardNudgeMFA { Write-LogMessage -API 'Standards' -tenant $Tenant -message "Authenticator App Nudge is not enabled with a snooze duration of $($CurrentState.registrationEnforcement.authenticationMethodsRegistrationCampaign.snoozeDurationInDays)" -sev Alert } } + } From 1c63f4f64946b7385ee85a0f16c35815ee4b6132 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 25 Feb 2025 13:11:17 -0500 Subject: [PATCH 063/167] handle no tenants on list --- .../HTTP Functions/CIPP/Settings/Invoke-ExecAccessChecks.ps1 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecAccessChecks.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecAccessChecks.ps1 index 4568e389f721..8df5f7fe9c37 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecAccessChecks.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecAccessChecks.ps1 @@ -75,6 +75,10 @@ Function Invoke-ExecAccessChecks { } catch { $LastRun = $null } + + if (!$Results) { + $Results = @() + } } catch { Write-Host $_.Exception.Message $Results = @() From 70ae81966bc95c5c119d94954aee28b8a9d9fb92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Tue, 25 Feb 2025 19:15:42 +0100 Subject: [PATCH 064/167] fix: standardize variable naming and improve error handling in Invoke-RemoveApp function --- .../Applications/Invoke-RemoveApp.ps1 | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-RemoveApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-RemoveApp.ps1 index a58aa9f73140..3f9f1b3596f4 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-RemoveApp.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-RemoveApp.ps1 @@ -11,30 +11,31 @@ Function Invoke-RemoveApp { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $User = $Request.Headers - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $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. $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter $policyId = $Request.Query.ID ?? $Request.Body.ID + if (!$policyId) { exit } try { #$unAssignRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($policyId)')/assign" -type POST -Body '{"assignments":[]}' -tenant $TenantFilter $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/$($policyId)" -type DELETE -tenant $TenantFilter $Result = "Successfully deleted app with $policyId" - Write-LogMessage -Headers $User -API $APINAME -message $Result -Sev 'Info' -tenant $TenantFilter + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev Info -tenant $TenantFilter + $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - $Result = "Could not delete app with $policyId. Error: $($ErrorMessage.NormalizedError)" - Write-LogMessage -Headers $User -API $APINAME -message $Result -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - + $Result = "Failed to delete app with $policyId. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev Error -tenant $TenantFilter -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } - $Body = [pscustomobject]@{Results = "$Result" } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Body + StatusCode = $StatusCode + Body = @{'Results' = "$Result" } }) From e509cb1b20649993f24a5e6e941f747590dbe274 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 25 Feb 2025 13:52:46 -0500 Subject: [PATCH 065/167] improve error message for gdap invites --- .../HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPInvite.ps1 | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPInvite.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPInvite.ps1 index 04e76f5997d0..cdfc60021116 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPInvite.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPInvite.ps1 @@ -82,7 +82,14 @@ Function Invoke-ExecGDAPInvite { } catch { $Message = 'Error creating GDAP relationship, failed at step: ' + $Step Write-Host "GDAP ERROR: $($_.InvocationInfo.PositionMessage)" - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $env:TenantID -message "$($Message): $($_.Exception.Message)" -Sev 'Error' -LogData (Get-CippException -Exception $_) + + if ($Step -eq 'Creating GDAP relationship' -and $_.Exception.Message -match 'The user (principal) does not have the required permissions to perform the specified action on the resource.') { + $Message = 'Error creating GDAP relationship, ensure that all users have MFA enabled and enforced without exception. Please see the Microsoft Partner Security Requirements documentation for more information. https://learn.microsoft.com/en-us/partner-center/security/partner-security-requirements' + } else { + $Message = "$($Message): $($_.Exception.Message)" + } + + Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $env:TenantID -message $Message -Sev 'Error' -LogData (Get-CippException -Exception $_) } $body = @{ From e6b7ee5c702182bf86afd53f3a878170325209de Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 25 Feb 2025 13:57:19 -0500 Subject: [PATCH 066/167] remove start/stop log on standards orch --- Modules/CIPPCore/Public/Invoke-CIPPStandardsRun.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/CIPPCore/Public/Invoke-CIPPStandardsRun.ps1 b/Modules/CIPPCore/Public/Invoke-CIPPStandardsRun.ps1 index 2b2016230ad6..6828a6da71ca 100644 --- a/Modules/CIPPCore/Public/Invoke-CIPPStandardsRun.ps1 +++ b/Modules/CIPPCore/Public/Invoke-CIPPStandardsRun.ps1 @@ -34,6 +34,7 @@ function Invoke-CIPPStandardsRun { runManually = $runManually } } + SkipLog = $true } if ($TemplateID) { $InputObject.QueueFunction.StandardParams['TemplateId'] = $TemplateID From d844722944b328e1582a5dd41edd313aae186baf Mon Sep 17 00:00:00 2001 From: Esco Date: Tue, 25 Feb 2025 20:14:09 +0100 Subject: [PATCH 067/167] chore: switch to LF and add .gitattributes --- .editorconfig | 4 ++-- .gitattributes | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 .gitattributes diff --git a/.editorconfig b/.editorconfig index b0c2c5085172..eecafcffcb70 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,12 +8,12 @@ insert_final_newline = true [*.{ps1, psd1, psm1}] indent_size = 4 -end_of_line = crlf +end_of_line = lf trim_trailing_whitespace = true [*.json] indent_size = 2 -end_of_line = crlf +end_of_line = lf trim_trailing_whitespace = true [*.{md, txt}] diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000000..6b7b1bb62a3f --- /dev/null +++ b/.gitattributes @@ -0,0 +1,13 @@ +* text=lf + +*.txt text eol=crlf +*.md text eol=crlf + +*.ps1 text eol=lf +*.psd1 text eol=lf +*.psm1 text eol=lf + +*.json text eol=lf + +*.png binary +*.jpg binary From eda10552afaa46596db70cf7734df88064f7162f Mon Sep 17 00:00:00 2001 From: Esco Date: Tue, 25 Feb 2025 20:18:56 +0100 Subject: [PATCH 068/167] chore: change to LF end lines --- Tools/Update-StandardsComments.ps1 | 304 ++++++++++++++--------------- 1 file changed, 152 insertions(+), 152 deletions(-) diff --git a/Tools/Update-StandardsComments.ps1 b/Tools/Update-StandardsComments.ps1 index 6f5cc8397db9..e804aefe0998 100644 --- a/Tools/Update-StandardsComments.ps1 +++ b/Tools/Update-StandardsComments.ps1 @@ -1,152 +1,152 @@ -<# -.SYNOPSIS - This script updates the comment block in the CIPP standard files. - -.DESCRIPTION - The script reads the standards.json file and updates the comment block in the corresponding CIPP standard files. - It adds or modifies the comment block based on the properties defined in the standards.json file. - This is made to be able to generate the help documentation for the CIPP standards automatically. - -.INPUTS - None. You cannot pipe objects to this script. - -.OUTPUTS - None. The script modifies the CIPP standard files directly. - -.NOTES - .FUNCTIONALITY Internal needs to be present in the comment block for the script, otherwise it will not be updated. - This is done as a safety measure to avoid updating the wrong files. - -.EXAMPLE - Update-StandardsComments.ps1 - - This example runs the script to update the comment block in the CIPP standard files. - -#> -param ( - [switch]$WhatIf -) - - -function EscapeMarkdown([object]$InputObject) { - # https://github.com/microsoft/FormatPowerShellToMarkdownTable/blob/master/src/FormatMarkdownTable/FormatMarkdownTable.psm1 - $Temp = '' - - if ($null -eq $InputObject) { - return '' - } elseif ($InputObject.GetType().BaseType -eq [System.Array]) { - $Temp = '{' + [System.String]::Join(', ', $InputObject) + '}' - } elseif ($InputObject.GetType() -eq [System.Collections.ArrayList] -or $InputObject.GetType().ToString().StartsWith('System.Collections.Generic.List')) { - $Temp = '{' + [System.String]::Join(', ', $InputObject.ToArray()) + '}' - } elseif (Get-Member -InputObject $InputObject -Name ToString -MemberType Method) { - $Temp = $InputObject.ToString() - } else { - $Temp = '' - } - - return $Temp.Replace('\', '\\').Replace('*', '\*').Replace('_', '\_').Replace("``", "\``").Replace('$', '\$').Replace('|', '\|').Replace('<', '\<').Replace('>', '\>').Replace([System.Environment]::NewLine, '
') -} - - -# Find the paths to the standards.json file based on the current script path -$StandardsJSONPath = Split-Path (Split-Path $PSScriptRoot) -$StandardsJSONPath = Resolve-Path "$StandardsJSONPath\*\src\data\standards.json" -$StandardsInfo = Get-Content -Path $StandardsJSONPath | ConvertFrom-Json -Depth 10 - -foreach ($Standard in $StandardsInfo) { - - # Calculate the standards file name and path - $StandardFileName = $Standard.name -replace 'standards.', 'Invoke-CIPPStandard' - $StandardsFilePath = Resolve-Path "$(Split-Path $PSScriptRoot)\Modules\CIPPCore\Public\Standards\$StandardFileName.ps1" - if (-not (Test-Path $StandardsFilePath)) { - Write-Host "No file found for standard $($Standard.name)" -ForegroundColor Yellow - continue - } - $Content = (Get-Content -Path $StandardsFilePath -Raw).TrimEnd() + "`r`n" - - # Remove random newlines before the param block - $regexPattern = '#>\s*\r?\n\s*\r?\n\s*param' - $Content = $Content -replace $regexPattern, "#>`r`n`r`n param" - - # Regex to match the existing comment block - $Regex = '<#(.|\n)*?\.FUNCTIONALITY\s*Internal(.|\n)*?#>' - - if ($Content -match $Regex) { - $NewComment = [System.Collections.Generic.List[string]]::new() - # Add the initial static comments - $NewComment.Add("<#`r`n") - $NewComment.Add(" .FUNCTIONALITY`r`n") - $NewComment.Add(" Internal`r`n") - $NewComment.Add(" .COMPONENT`r`n") - $NewComment.Add(" (APIName) $($Standard.name -replace 'standards.', '')`r`n") - $NewComment.Add(" .SYNOPSIS`r`n") - $NewComment.Add(" (Label) $($Standard.label.ToString())`r`n") - $NewComment.Add(" .DESCRIPTION`r`n") - if ([string]::IsNullOrWhiteSpace($Standard.docsDescription)) { - $NewComment.Add(" (Helptext) $($Standard.helpText.ToString())`r`n") - $NewComment.Add(" (DocsDescription) $(EscapeMarkdown($Standard.helpText.ToString()))`r`n") - } else { - $NewComment.Add(" (Helptext) $($Standard.helpText.ToString())`r`n") - $NewComment.Add(" (DocsDescription) $(EscapeMarkdown($Standard.docsDescription.ToString()))`r`n") - } - $NewComment.Add(" .NOTES`r`n") - - # Loop through the rest of the properties of the standard and add them to the NOTES field - foreach ($Property in $Standard.PSObject.Properties) { - switch ($Property.Name) { - 'name' { continue } - 'impactColour' { continue } - 'docsDescription' { continue } - 'helpText' { continue } - 'label' { continue } - Default { - $NewComment.Add(" $($Property.Name.ToUpper())`r`n") - if ($Property.Value -is [System.Object[]]) { - foreach ($Value in $Property.Value) { - $NewComment.Add(" $(ConvertTo-Json -InputObject $Value -Depth 5 -Compress)`r`n") - } - continue - } - $NewComment.Add(" $(EscapeMarkdown($Property.Value.ToString()))`r`n") - } - } - - } - - # Add header about how to update the comment block with this script - $NewComment.Add(" UPDATECOMMENTBLOCK`r`n") - $NewComment.Add(" Run the Tools\Update-StandardsComments.ps1 script to update this comment block`r`n") - # -Online help link - $NewComment.Add(" .LINK`r`n") - $DocsLink = 'https://docs.cipp.app/user-documentation/tenant/standards/list-standards/' - - switch ($Standard.cat) { - 'Global Standards' { $DocsLink += 'global-standards#' + $Standard.impact.ToLower() -replace ' ', '-' } - 'Entra (AAD) Standards' { $DocsLink += 'entra-aad-standards#' + $Standard.impact.ToLower() -replace ' ', '-' } - 'Exchange Standards' { $DocsLink += 'exchange-standards#' + $Standard.impact.ToLower() -replace ' ', '-' } - 'Defender Standards' { $DocsLink += 'defender-standards#' + $Standard.impact.ToLower() -replace ' ', '-' } - 'Intune Standards' { $DocsLink += 'intune-standards#' + $Standard.impact.ToLower() -replace ' ', '-' } - 'SharePoint Standards' { $DocsLink += 'sharepoint-standards#' + $Standard.impact.ToLower() -replace ' ', '-' } - 'Teams Standards' { $DocsLink += 'teams-standards#' + $Standard.impact.ToLower() -replace ' ', '-' } - Default {} - } - - switch ($Standard.impact) { - condition { } - Default {} - } - - $NewComment.Add(" $DocsLink`r`n") - $NewComment.Add(' #>') - - # Write the new comment block to the file - if ($WhatIf.IsPresent) { - Write-Host "Would update $StandardsFilePath with the following comment block:" - $NewComment - } else { - $Content -replace $Regex, $NewComment | Set-Content -Path $StandardsFilePath -Encoding utf8 -NoNewline - } - } else { - Write-Host "No comment block found in $StandardsFilePath" -ForegroundColor Yellow - } -} +<# +.SYNOPSIS + This script updates the comment block in the CIPP standard files. + +.DESCRIPTION + The script reads the standards.json file and updates the comment block in the corresponding CIPP standard files. + It adds or modifies the comment block based on the properties defined in the standards.json file. + This is made to be able to generate the help documentation for the CIPP standards automatically. + +.INPUTS + None. You cannot pipe objects to this script. + +.OUTPUTS + None. The script modifies the CIPP standard files directly. + +.NOTES + .FUNCTIONALITY Internal needs to be present in the comment block for the script, otherwise it will not be updated. + This is done as a safety measure to avoid updating the wrong files. + +.EXAMPLE + Update-StandardsComments.ps1 + + This example runs the script to update the comment block in the CIPP standard files. + +#> +param ( + [switch]$WhatIf +) + + +function EscapeMarkdown([object]$InputObject) { + # https://github.com/microsoft/FormatPowerShellToMarkdownTable/blob/master/src/FormatMarkdownTable/FormatMarkdownTable.psm1 + $Temp = '' + + if ($null -eq $InputObject) { + return '' + } elseif ($InputObject.GetType().BaseType -eq [System.Array]) { + $Temp = '{' + [System.String]::Join(', ', $InputObject) + '}' + } elseif ($InputObject.GetType() -eq [System.Collections.ArrayList] -or $InputObject.GetType().ToString().StartsWith('System.Collections.Generic.List')) { + $Temp = '{' + [System.String]::Join(', ', $InputObject.ToArray()) + '}' + } elseif (Get-Member -InputObject $InputObject -Name ToString -MemberType Method) { + $Temp = $InputObject.ToString() + } else { + $Temp = '' + } + + return $Temp.Replace('\', '\\').Replace('*', '\*').Replace('_', '\_').Replace("``", "\``").Replace('$', '\$').Replace('|', '\|').Replace('<', '\<').Replace('>', '\>').Replace([System.Environment]::NewLine, '
') +} + + +# Find the paths to the standards.json file based on the current script path +$StandardsJSONPath = Split-Path (Split-Path $PSScriptRoot) +$StandardsJSONPath = Resolve-Path "$StandardsJSONPath\*\src\data\standards.json" +$StandardsInfo = Get-Content -Path $StandardsJSONPath | ConvertFrom-Json -Depth 10 + +foreach ($Standard in $StandardsInfo) { + + # Calculate the standards file name and path + $StandardFileName = $Standard.name -replace 'standards.', 'Invoke-CIPPStandard' + $StandardsFilePath = Resolve-Path "$(Split-Path $PSScriptRoot)\Modules\CIPPCore\Public\Standards\$StandardFileName.ps1" + if (-not (Test-Path $StandardsFilePath)) { + Write-Host "No file found for standard $($Standard.name)" -ForegroundColor Yellow + continue + } + $Content = (Get-Content -Path $StandardsFilePath -Raw).TrimEnd() + "`n" + + # Remove random newlines before the param block + $regexPattern = '#>\s*\r?\n\s*\r?\n\s*param' + $Content = $Content -replace $regexPattern, "#>`n`n param" + + # Regex to match the existing comment block + $Regex = '<#(.|\n)*?\.FUNCTIONALITY\s*Internal(.|\n)*?#>' + + if ($Content -match $Regex) { + $NewComment = [System.Collections.Generic.List[string]]::new() + # Add the initial static comments + $NewComment.Add("<#`n") + $NewComment.Add(" .FUNCTIONALITY`n") + $NewComment.Add(" Internal`n") + $NewComment.Add(" .COMPONENT`n") + $NewComment.Add(" (APIName) $($Standard.name -replace 'standards.', '')`n") + $NewComment.Add(" .SYNOPSIS`n") + $NewComment.Add(" (Label) $($Standard.label.ToString())`n") + $NewComment.Add(" .DESCRIPTION`n") + if ([string]::IsNullOrWhiteSpace($Standard.docsDescription)) { + $NewComment.Add(" (Helptext) $($Standard.helpText.ToString())`n") + $NewComment.Add(" (DocsDescription) $(EscapeMarkdown($Standard.helpText.ToString()))`n") + } else { + $NewComment.Add(" (Helptext) $($Standard.helpText.ToString())`n") + $NewComment.Add(" (DocsDescription) $(EscapeMarkdown($Standard.docsDescription.ToString()))`n") + } + $NewComment.Add(" .NOTES`n") + + # Loop through the rest of the properties of the standard and add them to the NOTES field + foreach ($Property in $Standard.PSObject.Properties) { + switch ($Property.Name) { + 'name' { continue } + 'impactColour' { continue } + 'docsDescription' { continue } + 'helpText' { continue } + 'label' { continue } + Default { + $NewComment.Add(" $($Property.Name.ToUpper())`n") + if ($Property.Value -is [System.Object[]]) { + foreach ($Value in $Property.Value) { + $NewComment.Add(" $(ConvertTo-Json -InputObject $Value -Depth 5 -Compress)`n") + } + continue + } + $NewComment.Add(" $(EscapeMarkdown($Property.Value.ToString()))`n") + } + } + + } + + # Add header about how to update the comment block with this script + $NewComment.Add(" UPDATECOMMENTBLOCK`n") + $NewComment.Add(" Run the Tools\Update-StandardsComments.ps1 script to update this comment block`n") + # -Online help link + $NewComment.Add(" .LINK`n") + $DocsLink = 'https://docs.cipp.app/user-documentation/tenant/standards/list-standards/' + + switch ($Standard.cat) { + 'Global Standards' { $DocsLink += 'global-standards#' + $Standard.impact.ToLower() -replace ' ', '-' } + 'Entra (AAD) Standards' { $DocsLink += 'entra-aad-standards#' + $Standard.impact.ToLower() -replace ' ', '-' } + 'Exchange Standards' { $DocsLink += 'exchange-standards#' + $Standard.impact.ToLower() -replace ' ', '-' } + 'Defender Standards' { $DocsLink += 'defender-standards#' + $Standard.impact.ToLower() -replace ' ', '-' } + 'Intune Standards' { $DocsLink += 'intune-standards#' + $Standard.impact.ToLower() -replace ' ', '-' } + 'SharePoint Standards' { $DocsLink += 'sharepoint-standards#' + $Standard.impact.ToLower() -replace ' ', '-' } + 'Teams Standards' { $DocsLink += 'teams-standards#' + $Standard.impact.ToLower() -replace ' ', '-' } + Default {} + } + + switch ($Standard.impact) { + condition { } + Default {} + } + + $NewComment.Add(" $DocsLink`n") + $NewComment.Add(' #>') + + # Write the new comment block to the file + if ($WhatIf.IsPresent) { + Write-Host "Would update $StandardsFilePath with the following comment block:" + $NewComment + } else { + $Content -replace $Regex, $NewComment | Set-Content -Path $StandardsFilePath -Encoding utf8 -NoNewline + } + } else { + Write-Host "No comment block found in $StandardsFilePath" -ForegroundColor Yellow + } +} From 6b26d5418cf40100ab8a91536eeb5ec651086808 Mon Sep 17 00:00:00 2001 From: Esco Date: Tue, 25 Feb 2025 20:43:01 +0100 Subject: [PATCH 069/167] chore: rerun Update-StandardsComments.ps1 and CRLF to LF --- ...nvoke-CIPPStandardActivityBasedTimeout.ps1 | 2 + .../Standards/Invoke-CIPPStandardAddDKIM.ps1 | 2 + .../Invoke-CIPPStandardAnonReportDisable.ps1 | 2 + .../Invoke-CIPPStandardAntiPhishPolicy.ps1 | 444 +++++++++--------- .../Invoke-CIPPStandardAntiSpamSafeList.ps1 | 2 + .../Invoke-CIPPStandardAppDeploy.ps1 | 2 + .../Invoke-CIPPStandardAtpPolicyForO365.ps1 | 150 +++--- .../Standards/Invoke-CIPPStandardAuditLog.ps1 | 2 + ...Invoke-CIPPStandardAuthMethodsSettings.ps1 | 2 + .../Invoke-CIPPStandardAutoAddProxy.ps1 | 2 + .../Invoke-CIPPStandardAutoExpandArchive.ps1 | 2 + .../Standards/Invoke-CIPPStandardBookings.ps1 | 2 + .../Standards/Invoke-CIPPStandardBranding.ps1 | 2 + .../Invoke-CIPPStandardCloudMessageRecall.ps1 | 2 + ...-CIPPStandardConditionalAccessTemplate.ps1 | 2 + .../Invoke-CIPPStandardDelegateSentItems.ps1 | 2 + ...voke-CIPPStandardDeletedUserRentention.ps1 | 2 + ...PStandardDisableAddShortcutsToOneDrive.ps1 | 2 + ...ndardDisableAdditionalStorageProviders.ps1 | 2 + .../Invoke-CIPPStandardDisableAppCreation.ps1 | 2 + ...nvoke-CIPPStandardDisableBasicAuthSMTP.ps1 | 2 + .../Invoke-CIPPStandardDisableEmail.ps1 | 2 + ...StandardDisableExternalCalendarSharing.ps1 | 2 + ...voke-CIPPStandardDisableGuestDirectory.ps1 | 2 + .../Invoke-CIPPStandardDisableGuests.ps1 | 2 + ...voke-CIPPStandardDisableM365GroupUsers.ps1 | 2 + ...nvoke-CIPPStandardDisableOutlookAddins.ps1 | 2 + .../Invoke-CIPPStandardDisableQRCodePin.ps1 | 2 + .../Invoke-CIPPStandardDisableReshare.ps1 | 2 + .../Invoke-CIPPStandardDisableSMS.ps1 | 2 + ...-CIPPStandardDisableSecurityGroupUsers.ps1 | 2 + ...CIPPStandardDisableSelfServiceLicenses.ps1 | 2 + ...IPPStandardDisableSharePointLegacyAuth.ps1 | 2 + ...nvoke-CIPPStandardDisableSharedMailbox.ps1 | 2 + .../Invoke-CIPPStandardDisableTNEF.ps1 | 2 + ...voke-CIPPStandardDisableTenantCreation.ps1 | 2 + ...voke-CIPPStandardDisableUserSiteCreate.ps1 | 2 + .../Invoke-CIPPStandardDisableViva.ps1 | 2 + .../Invoke-CIPPStandardDisableVoice.ps1 | 2 + ...oke-CIPPStandardDisablex509Certificate.ps1 | 2 + ...e-CIPPStandardEXODisableAutoForwarding.ps1 | 2 + ...e-CIPPStandardEnableAppConsentRequests.ps1 | 2 + ...voke-CIPPStandardEnableCustomerLockbox.ps1 | 2 + .../Invoke-CIPPStandardEnableFIDO2.ps1 | 2 + ...Invoke-CIPPStandardEnableHardwareOAuth.ps1 | 2 + ...nvoke-CIPPStandardEnableLitigationHold.ps1 | 156 +++--- .../Invoke-CIPPStandardEnableMailTips.ps1 | 4 +- ...voke-CIPPStandardEnableMailboxAuditing.ps1 | 2 + ...voke-CIPPStandardEnableOnlineArchiving.ps1 | 2 + .../Invoke-CIPPStandardEnablePronouns.ps1 | 2 + .../Invoke-CIPPStandardExcludedfileExt.ps1 | 2 + .../Invoke-CIPPStandardExternalMFATrusted.ps1 | 2 + .../Invoke-CIPPStandardFocusedInbox.ps1 | 2 + ...PStandardGlobalQuarantineNotifications.ps1 | 2 + .../Invoke-CIPPStandardGroupTemplate.ps1 | 2 + .../Invoke-CIPPStandardGuestInvite.ps1 | 154 +++--- ...e-CIPPStandardIntuneComplianceSettings.ps1 | 156 +++--- .../Invoke-CIPPStandardIntuneTemplate.ps1 | 3 + .../Invoke-CIPPStandardLegacyMFACleanup.ps1 | 2 + .../Standards/Invoke-CIPPStandardMDMScope.ps1 | 250 +++++----- .../Invoke-CIPPStandardMailContacts.ps1 | 2 + ...Invoke-CIPPStandardMalwareFilterPolicy.ps1 | 344 +++++++------- .../Invoke-CIPPStandardMessageExpiration.ps1 | 2 + .../Standards/Invoke-CIPPStandardNudgeMFA.ps1 | 4 +- .../Invoke-CIPPStandardOauthConsent.ps1 | 2 + .../Invoke-CIPPStandardOauthConsentLowSec.ps1 | 2 + .../Invoke-CIPPStandardOutBoundSpamAlert.ps1 | 2 + ...CIPPStandardPWcompanionAppAllowedState.ps1 | 2 + ...rdPWdisplayAppInformationRequiredState.ps1 | 2 + ...oke-CIPPStandardPasswordExpireDisabled.ps1 | 2 + .../Invoke-CIPPStandardPerUserMFA.ps1 | 2 + .../Invoke-CIPPStandardPhishProtection.ps1 | 2 + .../Invoke-CIPPStandardProfilePhotos.ps1 | 2 + ...oke-CIPPStandardQuarantineRequestAlert.ps1 | 176 +++---- .../Invoke-CIPPStandardRetentionPolicyTag.ps1 | 2 + .../Invoke-CIPPStandardRotateDKIM.ps1 | 2 + .../Invoke-CIPPStandardSPAzureB2B.ps1 | 136 +++--- .../Invoke-CIPPStandardSPDirectSharing.ps1 | 138 +++--- ...e-CIPPStandardSPDisableLegacyWorkflows.ps1 | 138 +++--- ...ke-CIPPStandardSPDisallowInfectedFiles.ps1 | 138 +++--- .../Invoke-CIPPStandardSPEmailAttestation.ps1 | 144 +++--- ...e-CIPPStandardSPExternalUserExpiration.ps1 | 142 +++--- .../Invoke-CIPPStandardSPSyncButtonState.ps1 | 2 + ...nvoke-CIPPStandardSafeAttachmentPolicy.ps1 | 340 +++++++------- .../Invoke-CIPPStandardSafeLinksPolicy.ps1 | 356 +++++++------- .../Invoke-CIPPStandardSafeSendersDisable.ps1 | 2 + .../Invoke-CIPPStandardSecurityDefaults.ps1 | 2 + .../Invoke-CIPPStandardSendFromAlias.ps1 | 2 + ...oke-CIPPStandardSendReceiveLimitTenant.ps1 | 6 +- .../Invoke-CIPPStandardShortenMeetings.ps1 | 6 +- .../Invoke-CIPPStandardSpamFilterPolicy.ps1 | 376 +++++++-------- .../Invoke-CIPPStandardSpoofWarn.ps1 | 2 + .../Invoke-CIPPStandardStaleEntraDevices.ps1 | 2 + .../Standards/Invoke-CIPPStandardTAP.ps1 | 2 + ...voke-CIPPStandardTeamsEmailIntegration.ps1 | 142 +++--- .../Invoke-CIPPStandardTeamsEnrollUser.ps1 | 140 +++--- ...-CIPPStandardTeamsExternalAccessPolicy.ps1 | 156 +++--- ...e-CIPPStandardTeamsExternalFileSharing.ps1 | 172 +++---- ...PPStandardTeamsFederationConfiguration.ps1 | 236 +++++----- ...e-CIPPStandardTeamsGlobalMeetingPolicy.ps1 | 173 +++---- ...oke-CIPPStandardTeamsMeetingsByDefault.ps1 | 2 + ...nvoke-CIPPStandardTeamsMessagingPolicy.ps1 | 202 ++++---- ...voke-CIPPStandardTenantDefaultTimezone.ps1 | 2 + ...voke-CIPPStandardTransportRuleTemplate.ps1 | 2 + .../Invoke-CIPPStandardUndoOauth.ps1 | 2 + .../Invoke-CIPPStandardUserSubmissions.ps1 | 2 + .../Invoke-CIPPStandardallowOAuthTokens.ps1 | 2 + .../Invoke-CIPPStandardallowOTPTokens.ps1 | 2 + .../Invoke-CIPPStandardcalDefault.ps1 | 2 + .../Invoke-CIPPStandarddisableMacSync.ps1 | 2 + ...voke-CIPPStandardintuneBrandingProfile.ps1 | 202 ++++---- .../Invoke-CIPPStandardintuneDeviceReg.ps1 | 2 + ...CIPPStandardintuneDeviceRetirementDays.ps1 | 2 + .../Invoke-CIPPStandardintuneRequireMFA.ps1 | 2 + .../Standards/Invoke-CIPPStandardlaps.ps1 | 2 + .../Invoke-CIPPStandardsharingCapability.ps1 | 2 + ...e-CIPPStandardsharingDomainRestriction.ps1 | 186 ++++---- .../Invoke-CIPPStandardunmanagedSync.ps1 | 2 + 118 files changed, 2891 insertions(+), 2653 deletions(-) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 index 335d860c6200..22ac25cb001a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardActivityBasedTimeout.ps1 @@ -19,6 +19,8 @@ function Invoke-CIPPStandardActivityBasedTimeout { {"type":"autoComplete","multiple":false,"creatable":false,"label":"Select value","name":"standards.ActivityBasedTimeout.timeout","options":[{"label":"1 Hour","value":"01:00:00"},{"label":"3 Hours","value":"03:00:00"},{"label":"6 Hours","value":"06:00:00"},{"label":"12 Hours","value":"12:00:00"},{"label":"24 Hours","value":"1.00:00:00"}]} IMPACT Medium Impact + ADDEDDATE + 2022-04-13 POWERSHELLEQUIVALENT Portal or Graph API RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 index a57df85e9e4a..9625f199fec9 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardAddDKIM { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2023-03-14 POWERSHELLEQUIVALENT New-DkimSigningConfig and Set-DkimSigningConfig RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAnonReportDisable.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAnonReportDisable.ps1 index 23fbae4dc8f8..c44bafe196c3 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAnonReportDisable.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAnonReportDisable.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardAnonReportDisable { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2021-11-16 POWERSHELLEQUIVALENT Update-MgBetaAdminReportSetting -BodyParameter @{displayConcealedNames = \$true} RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 index 8e3eee48d96c..9f577250c442 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 @@ -1,221 +1,223 @@ -function Invoke-CIPPStandardAntiPhishPolicy { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) AntiPhishPolicy - .SYNOPSIS - (Label) Default Anti-Phishing Policy - .DESCRIPTION - (Helptext) This creates a Anti-Phishing policy that automatically enables Mailbox Intelligence and spoofing, optional switches for Mailtips. - (DocsDescription) This creates a Anti-Phishing policy that automatically enables Mailbox Intelligence and spoofing, optional switches for Mailtips. - .NOTES - CAT - Defender Standards - TAG - "CIS" - "mdo_safeattachments" - "mdo_highconfidencespamaction" - "mdo_highconfidencephishaction" - "mdo_phisspamacation" - "mdo_spam_notifications_only_for_admins" - "mdo_antiphishingpolicies" - "mdo_phishthresholdlevel" - ADDEDCOMPONENT - {"type":"number","label":"Phishing email threshold. (Default 1)","name":"standards.AntiPhishPolicy.PhishThresholdLevel","default":1} - {"type":"switch","label":"Show first contact safety tip","name":"standards.AntiPhishPolicy.EnableFirstContactSafetyTips","default":true} - {"type":"switch","label":"Show user impersonation safety tip","name":"standards.AntiPhishPolicy.EnableSimilarUsersSafetyTips","default":true} - {"type":"switch","label":"Show domain impersonation safety tip","name":"standards.AntiPhishPolicy.EnableSimilarDomainsSafetyTips","default":true} - {"type":"switch","label":"Show user impersonation unusual characters safety tip","name":"standards.AntiPhishPolicy.EnableUnusualCharactersSafetyTips","default":true} - {"type":"select","multiple":false,"label":"If the message is detected as spoof by spoof intelligence","name":"standards.AntiPhishPolicy.AuthenticationFailAction","options":[{"label":"Quarantine the message","value":"Quarantine"},{"label":"Move to Junk Folder","value":"MoveToJmf"}]} - {"type":"select","multiple":false,"label":"Quarantine policy for Spoof","name":"standards.AntiPhishPolicy.SpoofQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} - {"type":"select","multiple":false,"label":"If a message is detected as user impersonation","name":"standards.AntiPhishPolicy.TargetedUserProtectionAction","options":[{"label":"Move to Junk Folder","value":"MoveToJmf"},{"label":"Delete the message before its delivered","value":"Delete"},{"label":"Quarantine the message","value":"Quarantine"}]} - {"type":"select","multiple":false,"label":"Quarantine policy for user impersonation","name":"standards.AntiPhishPolicy.TargetedUserQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} - {"type":"select","multiple":false,"label":"If a message is detected as domain impersonation","name":"standards.AntiPhishPolicy.TargetedDomainProtectionAction","options":[{"label":"Move to Junk Folder","value":"MoveToJmf"},{"label":"Delete the message before its delivered","value":"Delete"},{"label":"Quarantine the message","value":"Quarantine"}]} - {"type":"select","multiple":false,"label":"Quarantine policy for domain impersonation","name":"standards.AntiPhishPolicy.TargetedDomainQuarantineTag","options":[{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"},{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"}]} - {"type":"select","multiple":false,"label":"If Mailbox Intelligence detects an impersonated user","name":"standards.AntiPhishPolicy.MailboxIntelligenceProtectionAction","options":[{"label":"Move to Junk Folder","value":"MoveToJmf"},{"label":"Delete the message before its delivered","value":"Delete"},{"label":"Quarantine the message","value":"Quarantine"}]} - {"type":"select","multiple":false,"label":"Apply quarantine policy","name":"standards.AntiPhishPolicy.MailboxIntelligenceQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} - IMPACT - Low Impact - POWERSHELLEQUIVALENT - Set-AntiphishPolicy or New-AntiphishPolicy - RECOMMENDEDBY - "CIS" - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/defender-standards#low-impact - #> - - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'AntiPhishPolicy' - - $ServicePlans = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/subscribedSkus?$select=servicePlans' -tenantid $Tenant - $ServicePlans = $ServicePlans.servicePlans.servicePlanName - $MDOLicensed = $ServicePlans -contains "ATP_ENTERPRISE" - Write-Information "MDOLicensed: $MDOLicensed" - - $PolicyList = @('CIPP Default Anti-Phishing Policy','Default Anti-Phishing Policy') - $ExistingPolicy = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AntiPhishPolicy' | Where-Object -Property Name -In $PolicyList - if ($null -eq $ExistingPolicy.Name) { - $PolicyName = $PolicyList[0] - } else { - $PolicyName = $ExistingPolicy.Name - } - $RuleList = @( 'CIPP Default Anti-Phishing Rule','CIPP Default Anti-Phishing Policy') - $ExistingRule = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AntiPhishRule' | Where-Object -Property Name -In $RuleList - if ($null -eq $ExistingRule.Name) { - $RuleName = $RuleList[0] - } else { - $RuleName = $ExistingRule.Name - } - - $CurrentState = $ExistingPolicy | - Select-Object Name, Enabled, PhishThresholdLevel, EnableMailboxIntelligence, EnableMailboxIntelligenceProtection, EnableSpoofIntelligence, EnableFirstContactSafetyTips, EnableSimilarUsersSafetyTips, EnableSimilarDomainsSafetyTips, EnableUnusualCharactersSafetyTips, EnableUnauthenticatedSender, EnableViaTag, AuthenticationFailAction, SpoofQuarantineTag, MailboxIntelligenceProtectionAction, MailboxIntelligenceQuarantineTag, TargetedUserProtectionAction, TargetedUserQuarantineTag, TargetedDomainProtectionAction, TargetedDomainQuarantineTag, EnableOrganizationDomainsProtection - - if ($MDOLicensed) { - $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and - ($CurrentState.Enabled -eq $true) -and - ($CurrentState.PhishThresholdLevel -eq $Settings.PhishThresholdLevel) -and - ($CurrentState.EnableMailboxIntelligence -eq $true) -and - ($CurrentState.EnableMailboxIntelligenceProtection -eq $true) -and - ($CurrentState.EnableSpoofIntelligence -eq $true) -and - ($CurrentState.EnableFirstContactSafetyTips -eq $Settings.EnableFirstContactSafetyTips) -and - ($CurrentState.EnableSimilarUsersSafetyTips -eq $Settings.EnableSimilarUsersSafetyTips) -and - ($CurrentState.EnableSimilarDomainsSafetyTips -eq $Settings.EnableSimilarDomainsSafetyTips) -and - ($CurrentState.EnableUnusualCharactersSafetyTips -eq $Settings.EnableUnusualCharactersSafetyTips) -and - ($CurrentState.EnableUnauthenticatedSender -eq $true) -and - ($CurrentState.EnableViaTag -eq $true) -and - ($CurrentState.AuthenticationFailAction -eq $Settings.AuthenticationFailAction) -and - ($CurrentState.SpoofQuarantineTag -eq $Settings.SpoofQuarantineTag) -and - ($CurrentState.MailboxIntelligenceProtectionAction -eq $Settings.MailboxIntelligenceProtectionAction) -and - ($CurrentState.MailboxIntelligenceQuarantineTag -eq $Settings.MailboxIntelligenceQuarantineTag) -and - ($CurrentState.TargetedUserProtectionAction -eq $Settings.TargetedUserProtectionAction) -and - ($CurrentState.TargetedUserQuarantineTag -eq $Settings.TargetedUserQuarantineTag) -and - ($CurrentState.TargetedDomainProtectionAction -eq $Settings.TargetedDomainProtectionAction) -and - ($CurrentState.TargetedDomainQuarantineTag -eq $Settings.TargetedDomainQuarantineTag) -and - ($CurrentState.EnableOrganizationDomainsProtection -eq $true) - } else { - $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and - ($CurrentState.Enabled -eq $true) -and - ($CurrentState.EnableSpoofIntelligence -eq $true) -and - ($CurrentState.EnableFirstContactSafetyTips -eq $Settings.EnableFirstContactSafetyTips) -and - ($CurrentState.EnableUnauthenticatedSender -eq $true) -and - ($CurrentState.EnableViaTag -eq $true) -and - ($CurrentState.AuthenticationFailAction -eq $Settings.AuthenticationFailAction) -and - ($CurrentState.SpoofQuarantineTag -eq $Settings.SpoofQuarantineTag) - } - - $AcceptedDomains = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AcceptedDomain' - - $RuleState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AntiPhishRule' | - Where-Object -Property Name -EQ $RuleName | - Select-Object Name, AntiPhishPolicy, Priority, RecipientDomainIs - - $RuleStateIsCorrect = ($RuleState.Name -eq $RuleName) -and - ($RuleState.AntiPhishPolicy -eq $PolicyName) -and - ($RuleState.Priority -eq 0) -and - (!(Compare-Object -ReferenceObject $RuleState.RecipientDomainIs -DifferenceObject $AcceptedDomains.Name)) - - if ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Anti-phishing policy already correctly configured' -sev Info - } else { - if ($MDOLicensed) { - $cmdparams = @{ - Enabled = $true - PhishThresholdLevel = $Settings.PhishThresholdLevel - EnableMailboxIntelligence = $true - EnableMailboxIntelligenceProtection = $true - EnableSpoofIntelligence = $true - EnableFirstContactSafetyTips = $Settings.EnableFirstContactSafetyTips - EnableSimilarUsersSafetyTips = $Settings.EnableSimilarUsersSafetyTips - EnableSimilarDomainsSafetyTips = $Settings.EnableSimilarDomainsSafetyTips - EnableUnusualCharactersSafetyTips = $Settings.EnableUnusualCharactersSafetyTips - EnableUnauthenticatedSender = $true - EnableViaTag = $true - AuthenticationFailAction = $Settings.AuthenticationFailAction - SpoofQuarantineTag = $Settings.SpoofQuarantineTag - MailboxIntelligenceProtectionAction = $Settings.MailboxIntelligenceProtectionAction - MailboxIntelligenceQuarantineTag = $Settings.MailboxIntelligenceQuarantineTag - TargetedUserProtectionAction = $Settings.TargetedUserProtectionAction - TargetedUserQuarantineTag = $Settings.TargetedUserQuarantineTag - TargetedDomainProtectionAction = $Settings.TargetedDomainProtectionAction - TargetedDomainQuarantineTag = $Settings.TargetedDomainQuarantineTag - EnableOrganizationDomainsProtection = $true - } - } else { - $cmdparams = @{ - Enabled = $true - EnableSpoofIntelligence = $true - EnableFirstContactSafetyTips = $Settings.EnableFirstContactSafetyTips - EnableUnauthenticatedSender = $true - EnableViaTag = $true - AuthenticationFailAction = $Settings.AuthenticationFailAction - SpoofQuarantineTag = $Settings.SpoofQuarantineTag - } - } - - if ($CurrentState.Name -eq $PolicyName) { - try { - $cmdparams.Add('Identity', $PolicyName) - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-AntiPhishPolicy' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Anti-phishing policy $PolicyName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update Anti-phishing policy $PolicyName." -sev Error -LogData $_ - } - } else { - try { - $cmdparams.Add('Name', $PolicyName) - New-ExoRequest -tenantid $Tenant -cmdlet 'New-AntiPhishPolicy' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created Anti-phishing policy $PolicyName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Anti-phishing policy $PolicyName." -sev Error -LogData $_ - } - } - } - - if ($RuleStateIsCorrect -eq $false) { - $cmdparams = @{ - Priority = 0 - RecipientDomainIs = $AcceptedDomains.Name - } - - if ($RuleState.AntiPhishPolicy -ne $PolicyName) { - $cmdparams.Add('AntiPhishPolicy', $PolicyName) - } - - if ($RuleState.Name -eq $RuleName) { - try { - $cmdparams.Add('Identity', $RuleName) - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-AntiPhishRule' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Anti-phishing rule $RuleName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update Anti-phishing rule $RuleName." -sev Error -LogData $_ - } - } else { - try { - $cmdparams.Add('Name', $RuleName) - New-ExoRequest -tenantid $Tenant -cmdlet 'New-AntiPhishRule' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created Anti-phishing rule $RuleName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Anti-phishing rule $RuleName." -sev Error -LogData $_ - } - } - } - } - - if ($Settings.alert -eq $true) { - - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Anti-phishing policy is enabled' -sev Info - } else { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Anti-phishing policy is not enabled' -sev Alert - } - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'AntiPhishPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant - } - -} +function Invoke-CIPPStandardAntiPhishPolicy { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) AntiPhishPolicy + .SYNOPSIS + (Label) Default Anti-Phishing Policy + .DESCRIPTION + (Helptext) This creates a Anti-Phishing policy that automatically enables Mailbox Intelligence and spoofing, optional switches for Mailtips. + (DocsDescription) This creates a Anti-Phishing policy that automatically enables Mailbox Intelligence and spoofing, optional switches for Mailtips. + .NOTES + CAT + Defender Standards + TAG + "CIS" + "mdo_safeattachments" + "mdo_highconfidencespamaction" + "mdo_highconfidencephishaction" + "mdo_phisspamacation" + "mdo_spam_notifications_only_for_admins" + "mdo_antiphishingpolicies" + "mdo_phishthresholdlevel" + ADDEDCOMPONENT + {"type":"number","label":"Phishing email threshold. (Default 1)","name":"standards.AntiPhishPolicy.PhishThresholdLevel","defaultValue":1} + {"type":"switch","label":"Show first contact safety tip","name":"standards.AntiPhishPolicy.EnableFirstContactSafetyTips","defaultValue":true} + {"type":"switch","label":"Show user impersonation safety tip","name":"standards.AntiPhishPolicy.EnableSimilarUsersSafetyTips","defaultValue":true} + {"type":"switch","label":"Show domain impersonation safety tip","name":"standards.AntiPhishPolicy.EnableSimilarDomainsSafetyTips","defaultValue":true} + {"type":"switch","label":"Show user impersonation unusual characters safety tip","name":"standards.AntiPhishPolicy.EnableUnusualCharactersSafetyTips","defaultValue":true} + {"type":"select","multiple":false,"label":"If the message is detected as spoof by spoof intelligence","name":"standards.AntiPhishPolicy.AuthenticationFailAction","options":[{"label":"Quarantine the message","value":"Quarantine"},{"label":"Move to Junk Folder","value":"MoveToJmf"}]} + {"type":"select","multiple":false,"label":"Quarantine policy for Spoof","name":"standards.AntiPhishPolicy.SpoofQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} + {"type":"select","multiple":false,"label":"If a message is detected as user impersonation","name":"standards.AntiPhishPolicy.TargetedUserProtectionAction","options":[{"label":"Move to Junk Folder","value":"MoveToJmf"},{"label":"Delete the message before its delivered","value":"Delete"},{"label":"Quarantine the message","value":"Quarantine"}]} + {"type":"select","multiple":false,"label":"Quarantine policy for user impersonation","name":"standards.AntiPhishPolicy.TargetedUserQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} + {"type":"select","multiple":false,"label":"If a message is detected as domain impersonation","name":"standards.AntiPhishPolicy.TargetedDomainProtectionAction","options":[{"label":"Move to Junk Folder","value":"MoveToJmf"},{"label":"Delete the message before its delivered","value":"Delete"},{"label":"Quarantine the message","value":"Quarantine"}]} + {"type":"select","multiple":false,"label":"Quarantine policy for domain impersonation","name":"standards.AntiPhishPolicy.TargetedDomainQuarantineTag","options":[{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"},{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"}]} + {"type":"select","multiple":false,"label":"If Mailbox Intelligence detects an impersonated user","name":"standards.AntiPhishPolicy.MailboxIntelligenceProtectionAction","options":[{"label":"Move to Junk Folder","value":"MoveToJmf"},{"label":"Delete the message before its delivered","value":"Delete"},{"label":"Quarantine the message","value":"Quarantine"}]} + {"type":"select","multiple":false,"label":"Apply quarantine policy","name":"standards.AntiPhishPolicy.MailboxIntelligenceQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} + IMPACT + Low Impact + ADDEDDATE + 2024-03-25 + POWERSHELLEQUIVALENT + Set-AntiphishPolicy or New-AntiphishPolicy + RECOMMENDEDBY + "CIS" + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/defender-standards#low-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'AntiPhishPolicy' + + $ServicePlans = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/subscribedSkus?$select=servicePlans' -tenantid $Tenant + $ServicePlans = $ServicePlans.servicePlans.servicePlanName + $MDOLicensed = $ServicePlans -contains "ATP_ENTERPRISE" + Write-Information "MDOLicensed: $MDOLicensed" + + $PolicyList = @('CIPP Default Anti-Phishing Policy','Default Anti-Phishing Policy') + $ExistingPolicy = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AntiPhishPolicy' | Where-Object -Property Name -In $PolicyList + if ($null -eq $ExistingPolicy.Name) { + $PolicyName = $PolicyList[0] + } else { + $PolicyName = $ExistingPolicy.Name + } + $RuleList = @( 'CIPP Default Anti-Phishing Rule','CIPP Default Anti-Phishing Policy') + $ExistingRule = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AntiPhishRule' | Where-Object -Property Name -In $RuleList + if ($null -eq $ExistingRule.Name) { + $RuleName = $RuleList[0] + } else { + $RuleName = $ExistingRule.Name + } + + $CurrentState = $ExistingPolicy | + Select-Object Name, Enabled, PhishThresholdLevel, EnableMailboxIntelligence, EnableMailboxIntelligenceProtection, EnableSpoofIntelligence, EnableFirstContactSafetyTips, EnableSimilarUsersSafetyTips, EnableSimilarDomainsSafetyTips, EnableUnusualCharactersSafetyTips, EnableUnauthenticatedSender, EnableViaTag, AuthenticationFailAction, SpoofQuarantineTag, MailboxIntelligenceProtectionAction, MailboxIntelligenceQuarantineTag, TargetedUserProtectionAction, TargetedUserQuarantineTag, TargetedDomainProtectionAction, TargetedDomainQuarantineTag, EnableOrganizationDomainsProtection + + if ($MDOLicensed) { + $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and + ($CurrentState.Enabled -eq $true) -and + ($CurrentState.PhishThresholdLevel -eq $Settings.PhishThresholdLevel) -and + ($CurrentState.EnableMailboxIntelligence -eq $true) -and + ($CurrentState.EnableMailboxIntelligenceProtection -eq $true) -and + ($CurrentState.EnableSpoofIntelligence -eq $true) -and + ($CurrentState.EnableFirstContactSafetyTips -eq $Settings.EnableFirstContactSafetyTips) -and + ($CurrentState.EnableSimilarUsersSafetyTips -eq $Settings.EnableSimilarUsersSafetyTips) -and + ($CurrentState.EnableSimilarDomainsSafetyTips -eq $Settings.EnableSimilarDomainsSafetyTips) -and + ($CurrentState.EnableUnusualCharactersSafetyTips -eq $Settings.EnableUnusualCharactersSafetyTips) -and + ($CurrentState.EnableUnauthenticatedSender -eq $true) -and + ($CurrentState.EnableViaTag -eq $true) -and + ($CurrentState.AuthenticationFailAction -eq $Settings.AuthenticationFailAction) -and + ($CurrentState.SpoofQuarantineTag -eq $Settings.SpoofQuarantineTag) -and + ($CurrentState.MailboxIntelligenceProtectionAction -eq $Settings.MailboxIntelligenceProtectionAction) -and + ($CurrentState.MailboxIntelligenceQuarantineTag -eq $Settings.MailboxIntelligenceQuarantineTag) -and + ($CurrentState.TargetedUserProtectionAction -eq $Settings.TargetedUserProtectionAction) -and + ($CurrentState.TargetedUserQuarantineTag -eq $Settings.TargetedUserQuarantineTag) -and + ($CurrentState.TargetedDomainProtectionAction -eq $Settings.TargetedDomainProtectionAction) -and + ($CurrentState.TargetedDomainQuarantineTag -eq $Settings.TargetedDomainQuarantineTag) -and + ($CurrentState.EnableOrganizationDomainsProtection -eq $true) + } else { + $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and + ($CurrentState.Enabled -eq $true) -and + ($CurrentState.EnableSpoofIntelligence -eq $true) -and + ($CurrentState.EnableFirstContactSafetyTips -eq $Settings.EnableFirstContactSafetyTips) -and + ($CurrentState.EnableUnauthenticatedSender -eq $true) -and + ($CurrentState.EnableViaTag -eq $true) -and + ($CurrentState.AuthenticationFailAction -eq $Settings.AuthenticationFailAction) -and + ($CurrentState.SpoofQuarantineTag -eq $Settings.SpoofQuarantineTag) + } + + $AcceptedDomains = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AcceptedDomain' + + $RuleState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AntiPhishRule' | + Where-Object -Property Name -EQ $RuleName | + Select-Object Name, AntiPhishPolicy, Priority, RecipientDomainIs + + $RuleStateIsCorrect = ($RuleState.Name -eq $RuleName) -and + ($RuleState.AntiPhishPolicy -eq $PolicyName) -and + ($RuleState.Priority -eq 0) -and + (!(Compare-Object -ReferenceObject $RuleState.RecipientDomainIs -DifferenceObject $AcceptedDomains.Name)) + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Anti-phishing policy already correctly configured' -sev Info + } else { + if ($MDOLicensed) { + $cmdparams = @{ + Enabled = $true + PhishThresholdLevel = $Settings.PhishThresholdLevel + EnableMailboxIntelligence = $true + EnableMailboxIntelligenceProtection = $true + EnableSpoofIntelligence = $true + EnableFirstContactSafetyTips = $Settings.EnableFirstContactSafetyTips + EnableSimilarUsersSafetyTips = $Settings.EnableSimilarUsersSafetyTips + EnableSimilarDomainsSafetyTips = $Settings.EnableSimilarDomainsSafetyTips + EnableUnusualCharactersSafetyTips = $Settings.EnableUnusualCharactersSafetyTips + EnableUnauthenticatedSender = $true + EnableViaTag = $true + AuthenticationFailAction = $Settings.AuthenticationFailAction + SpoofQuarantineTag = $Settings.SpoofQuarantineTag + MailboxIntelligenceProtectionAction = $Settings.MailboxIntelligenceProtectionAction + MailboxIntelligenceQuarantineTag = $Settings.MailboxIntelligenceQuarantineTag + TargetedUserProtectionAction = $Settings.TargetedUserProtectionAction + TargetedUserQuarantineTag = $Settings.TargetedUserQuarantineTag + TargetedDomainProtectionAction = $Settings.TargetedDomainProtectionAction + TargetedDomainQuarantineTag = $Settings.TargetedDomainQuarantineTag + EnableOrganizationDomainsProtection = $true + } + } else { + $cmdparams = @{ + Enabled = $true + EnableSpoofIntelligence = $true + EnableFirstContactSafetyTips = $Settings.EnableFirstContactSafetyTips + EnableUnauthenticatedSender = $true + EnableViaTag = $true + AuthenticationFailAction = $Settings.AuthenticationFailAction + SpoofQuarantineTag = $Settings.SpoofQuarantineTag + } + } + + if ($CurrentState.Name -eq $PolicyName) { + try { + $cmdparams.Add('Identity', $PolicyName) + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-AntiPhishPolicy' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Anti-phishing policy $PolicyName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update Anti-phishing policy $PolicyName." -sev Error -LogData $_ + } + } else { + try { + $cmdparams.Add('Name', $PolicyName) + New-ExoRequest -tenantid $Tenant -cmdlet 'New-AntiPhishPolicy' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created Anti-phishing policy $PolicyName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Anti-phishing policy $PolicyName." -sev Error -LogData $_ + } + } + } + + if ($RuleStateIsCorrect -eq $false) { + $cmdparams = @{ + Priority = 0 + RecipientDomainIs = $AcceptedDomains.Name + } + + if ($RuleState.AntiPhishPolicy -ne $PolicyName) { + $cmdparams.Add('AntiPhishPolicy', $PolicyName) + } + + if ($RuleState.Name -eq $RuleName) { + try { + $cmdparams.Add('Identity', $RuleName) + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-AntiPhishRule' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Anti-phishing rule $RuleName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update Anti-phishing rule $RuleName." -sev Error -LogData $_ + } + } else { + try { + $cmdparams.Add('Name', $RuleName) + New-ExoRequest -tenantid $Tenant -cmdlet 'New-AntiPhishRule' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created Anti-phishing rule $RuleName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Anti-phishing rule $RuleName." -sev Error -LogData $_ + } + } + } + } + + if ($Settings.alert -eq $true) { + + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Anti-phishing policy is enabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Anti-phishing policy is not enabled' -sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'AntiPhishPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant + } + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiSpamSafeList.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiSpamSafeList.ps1 index 077877e36b32..3ea9d244aedc 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiSpamSafeList.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiSpamSafeList.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardAntiSpamSafeList { {"type":"switch","name":"standards.AntiSpamSafeList.EnableSafeList","label":"Enable Safe List"} IMPACT Medium Impact + ADDEDDATE + 2025-02-15 POWERSHELLEQUIVALENT Set-HostedConnectionFilterPolicy "Default" -EnableSafeList \$true RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAppDeploy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAppDeploy.ps1 index 4e6802efeb33..183feb83dfee 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAppDeploy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAppDeploy.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardAppDeploy { {"type":"textField","name":"standards.AppDeploy.appids","label":"Application IDs, comma separated"} IMPACT Low Impact + ADDEDDATE + 2024-07-07 POWERSHELLEQUIVALENT Portal or Graph API RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 index f7e369859105..45cd930a4cda 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 @@ -1,74 +1,76 @@ -function Invoke-CIPPStandardAtpPolicyForO365 { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) AtpPolicyForO365 - .SYNOPSIS - (Label) Default Atp Policy For O365 - .DESCRIPTION - (Helptext) This creates a Atp policy that enables Defender for Office 365 for SharePoint, OneDrive and Microsoft Teams. - (DocsDescription) This creates a Atp policy that enables Defender for Office 365 for SharePoint, OneDrive and Microsoft Teams. - .NOTES - CAT - Defender Standards - TAG - "CIS" - ADDEDCOMPONENT - {"type":"switch","label":"Allow people to click through Protected View even if Safe Documents identified the file as malicious","name":"standards.AtpPolicyForO365.AllowSafeDocsOpen","default":false,"required":false} - IMPACT - Low Impact - POWERSHELLEQUIVALENT - Set-AtpPolicyForO365 - RECOMMENDEDBY - "CIS" - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/defender-standards#low-impact - #> - - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'AtpPolicyForO365' - - $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AtpPolicyForO365' | - Select-Object EnableATPForSPOTeamsODB, EnableSafeDocs, AllowSafeDocsOpen - - $StateIsCorrect = ($CurrentState.EnableATPForSPOTeamsODB -eq $true) -and - ($CurrentState.EnableSafeDocs -eq $true) -and - ($CurrentState.AllowSafeDocsOpen -eq $Settings.AllowSafeDocsOpen) - - if ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Atp Policy For O365 already set.' -sev Info - } else { - $cmdparams = @{ - EnableATPForSPOTeamsODB = $true - EnableSafeDocs = $true - AllowSafeDocsOpen = $Settings.AllowSafeDocsOpen - } - - try { - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-AtpPolicyForO365' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated Atp Policy For O365' -sev Info - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Atp Policy For O365. Error: $ErrorMessage" -sev Error - } - } - } - - if ($Settings.alert -eq $true) { - - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Atp Policy For O365 is enabled' -sev Info - } else { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Atp Policy For O365 is not enabled' -sev Alert - } - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'AtpPolicyForO365' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant - } - -} +function Invoke-CIPPStandardAtpPolicyForO365 { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) AtpPolicyForO365 + .SYNOPSIS + (Label) Default Atp Policy For O365 + .DESCRIPTION + (Helptext) This creates a Atp policy that enables Defender for Office 365 for SharePoint, OneDrive and Microsoft Teams. + (DocsDescription) This creates a Atp policy that enables Defender for Office 365 for SharePoint, OneDrive and Microsoft Teams. + .NOTES + CAT + Defender Standards + TAG + "CIS" + ADDEDCOMPONENT + {"type":"switch","label":"Allow people to click through Protected View even if Safe Documents identified the file as malicious","name":"standards.AtpPolicyForO365.AllowSafeDocsOpen","defaultValue":false,"required":false} + IMPACT + Low Impact + ADDEDDATE + 2024-03-25 + POWERSHELLEQUIVALENT + Set-AtpPolicyForO365 + RECOMMENDEDBY + "CIS" + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/defender-standards#low-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'AtpPolicyForO365' + + $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AtpPolicyForO365' | + Select-Object EnableATPForSPOTeamsODB, EnableSafeDocs, AllowSafeDocsOpen + + $StateIsCorrect = ($CurrentState.EnableATPForSPOTeamsODB -eq $true) -and + ($CurrentState.EnableSafeDocs -eq $true) -and + ($CurrentState.AllowSafeDocsOpen -eq $Settings.AllowSafeDocsOpen) + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Atp Policy For O365 already set.' -sev Info + } else { + $cmdparams = @{ + EnableATPForSPOTeamsODB = $true + EnableSafeDocs = $true + AllowSafeDocsOpen = $Settings.AllowSafeDocsOpen + } + + try { + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-AtpPolicyForO365' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated Atp Policy For O365' -sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Atp Policy For O365. Error: $ErrorMessage" -sev Error + } + } + } + + if ($Settings.alert -eq $true) { + + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Atp Policy For O365 is enabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Atp Policy For O365 is not enabled' -sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'AtpPolicyForO365' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant + } + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 index c2ce718ae008..33f1ef104ac3 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 @@ -18,6 +18,8 @@ function Invoke-CIPPStandardAuditLog { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2021-11-16 POWERSHELLEQUIVALENT Enable-OrganizationCustomization RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuthMethodsSettings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuthMethodsSettings.ps1 index 18ab2554d4a5..d09843d89e70 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuthMethodsSettings.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuthMethodsSettings.ps1 @@ -18,6 +18,8 @@ function Invoke-CIPPStandardAuthMethodsSettings { {"type":"autoComplete","multiple":false,"creatable":false,"required":false,"name":"standards.AuthMethodsSettings.SystemCredential","label":"System Credential Preferences","options":[{"label":"Microsoft managed","value":"default"},{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} IMPACT Low Impact + ADDEDDATE + 2025-02-10 POWERSHELLEQUIVALENT Update-MgBetaPolicyAuthenticationMethodPolicy RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoAddProxy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoAddProxy.ps1 index 7ad0a6b2e11f..964706df5ae3 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoAddProxy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoAddProxy.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardAutoAddProxy { ADDEDCOMPONENT IMPACT Medium Impact + ADDEDDATE + 2025-02-07 POWERSHELLEQUIVALENT Set-Mailbox -EmailAddresses @{add=\$EmailAddress} RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoExpandArchive.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoExpandArchive.ps1 index 9945f982b524..bad412af24fd 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoExpandArchive.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoExpandArchive.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardAutoExpandArchive { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2021-11-16 POWERSHELLEQUIVALENT Set-OrganizationConfig -AutoExpandingArchive RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 index 94c7890adacf..4a6e949c4523 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardBookings { {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.Bookings.state","options":[{"label":"Enabled","value":"true"},{"label":"Disabled","value":"false"}]} IMPACT Medium Impact + ADDEDDATE + 2024-05-31 POWERSHELLEQUIVALENT Set-OrganizationConfig -BookingsEnabled RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBranding.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBranding.ps1 index d4190433c941..76365a928281 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBranding.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBranding.ps1 @@ -22,6 +22,8 @@ function Invoke-CIPPStandardBranding { {"type":"switch","name":"standards.Branding.isFooterShown","label":"Show footer"} IMPACT Low Impact + ADDEDDATE + 2024-05-13 POWERSHELLEQUIVALENT Portal only RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 index def36fadcb5e..3345291f41d3 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardCloudMessageRecall { {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.CloudMessageRecall.state","options":[{"label":"Enabled","value":"true"},{"label":"Disabled","value":"false"}]} IMPACT Low Impact + ADDEDDATE + 2024-05-31 POWERSHELLEQUIVALENT Set-OrganizationConfig -MessageRecallEnabled RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccessTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccessTemplate.ps1 index 4f3dcd23bad6..03105df1c8b5 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccessTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccessTemplate.ps1 @@ -18,6 +18,8 @@ function Invoke-CIPPStandardConditionalAccessTemplate { IMPACT High Impact + ADDEDDATE + 2023-12-30 ADDEDCOMPONENT {"type":"autoComplete","name":"TemplateList","multiple":false,"label":"Select Conditional Access Template","api":{"url":"/api/ListCATemplates","labelField":"displayName","valueField":"GUID","queryKey":"ListCATemplates"}} {"name":"state","label":"What state should we deploy this template in?","type":"radio","options":[{"value":"donotchange","label":"Do not change state"},{"value":"Enabled","label":"Set to enabled"},{"value":"Disabled","label":"Set to disabled"},{"value":"enabledForReportingButNotEnforced","label":"Set to report only"}]} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 index a1c724a7167d..b6035cb0cd9a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardDelegateSentItems { {"type":"switch","label":"Include user mailboxes","name":"standards.DelegateSentItems.IncludeUserMailboxes"} IMPACT Medium Impact + ADDEDDATE + 2021-11-16 POWERSHELLEQUIVALENT Set-Mailbox RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 index 428327b1fe99..75929ccdc116 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardDeletedUserRentention { {"type":"autoComplete","multiple":false,"name":"standards.DeletedUserRentention.Days","label":"Retention time (Default 30 days)","options":[{"label":"30 days","value":"30"},{"label":"90 days","value":"90"},{"label":"1 year","value":"365"},{"label":"2 years","value":"730"},{"label":"3 years","value":"1095"},{"label":"4 years","value":"1460"},{"label":"5 years","value":"1825"},{"label":"6 years","value":"2190"},{"label":"7 years","value":"2555"},{"label":"8 years","value":"2920"},{"label":"9 years","value":"3285"},{"label":"10 years","value":"3650"}]} IMPACT Low Impact + ADDEDDATE + 2022-06-15 POWERSHELLEQUIVALENT Update-MgBetaAdminSharePointSetting RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 index f488fd9e1e94..bf7928089d8f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardDisableAddShortcutsToOneDrive { {"type":"autoComplete","multiple":false,"creatable":false,"label":"Add Shortcuts To OneDrive button state","name":"standards.DisableAddShortcutsToOneDrive.state","options":[{"label":"Disabled","value":"true"},{"label":"Enabled","value":"false"}]} IMPACT Medium Impact + ADDEDDATE + 2023-07-25 POWERSHELLEQUIVALENT Set-SPOTenant -DisableAddShortcutsToOneDrive \$true or \$false RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAdditionalStorageProviders.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAdditionalStorageProviders.ps1 index 0335b7dcace4..e295651f6165 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAdditionalStorageProviders.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAdditionalStorageProviders.ps1 @@ -18,6 +18,8 @@ function Invoke-CIPPStandardDisableAdditionalStorageProviders { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2024-01-17 POWERSHELLEQUIVALENT Get-OwaMailboxPolicy \| Set-OwaMailboxPolicy -AdditionalStorageProvidersEnabled \$False RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAppCreation.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAppCreation.ps1 index 295d5e9b87f8..d22a1f88b8fa 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAppCreation.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAppCreation.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardDisableAppCreation { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2024-03-20 POWERSHELLEQUIVALENT Update-MgPolicyAuthorizationPolicy RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 index eb4de11a619a..feab61d0ee06 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardDisableBasicAuthSMTP { ADDEDCOMPONENT IMPACT Medium Impact + ADDEDDATE + 2021-11-16 POWERSHELLEQUIVALENT Set-TransportConfig -SmtpClientAuthenticationDisabled \$true RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableEmail.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableEmail.ps1 index b810f67f6c82..b85b0777b6f1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableEmail.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableEmail.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardDisableEmail { ADDEDCOMPONENT IMPACT High Impact + ADDEDDATE + 2023-12-18 POWERSHELLEQUIVALENT Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExternalCalendarSharing.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExternalCalendarSharing.ps1 index 8270a259292b..780a8177da55 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExternalCalendarSharing.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExternalCalendarSharing.ps1 @@ -18,6 +18,8 @@ function Invoke-CIPPStandardDisableExternalCalendarSharing { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2024-01-08 POWERSHELLEQUIVALENT Get-SharingPolicy \| Set-SharingPolicy -Enabled \$False RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuestDirectory.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuestDirectory.ps1 index e0ecf6b19586..d0661ab6a34b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuestDirectory.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuestDirectory.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardDisableGuestDirectory { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2022-05-04 POWERSHELLEQUIVALENT Set-AzureADMSAuthorizationPolicy -GuestUserRoleId '2af84b1e-32c8-42b7-82bc-daa82404023b' RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuests.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuests.ps1 index b17a84ee81f3..3271feda4b05 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuests.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableGuests.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardDisableGuests { ADDEDCOMPONENT IMPACT Medium Impact + ADDEDDATE + 2022-10-20 POWERSHELLEQUIVALENT Graph API RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableM365GroupUsers.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableM365GroupUsers.ps1 index b241ae9e19ca..12614ae0090e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableM365GroupUsers.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableM365GroupUsers.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardDisableM365GroupUsers { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2022-07-17 POWERSHELLEQUIVALENT Update-MgBetaDirectorySetting RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 index e011c6b46878..36dc84459f06 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 @@ -18,6 +18,8 @@ function Invoke-CIPPStandardDisableOutlookAddins { ADDEDCOMPONENT IMPACT Medium Impact + ADDEDDATE + 2024-02-05 POWERSHELLEQUIVALENT Get-ManagementRoleAssignment \| Remove-ManagementRoleAssignment RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableQRCodePin.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableQRCodePin.ps1 index ae8b46922a0a..98ce2c9b1158 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableQRCodePin.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableQRCodePin.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardDisableQRCodePin { ADDEDCOMPONENT IMPACT High Impact + ADDEDDATE + 2024-02-10 POWERSHELLEQUIVALENT Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 index 158c1fa7010b..8cdba0d63a8b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardDisableReshare { ADDEDCOMPONENT IMPACT High Impact + ADDEDDATE + 2022-06-15 POWERSHELLEQUIVALENT Update-MgBetaAdminSharePointSetting RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSMS.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSMS.ps1 index 5c79181d7879..b8e21c804f95 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSMS.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSMS.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardDisableSMS { ADDEDCOMPONENT IMPACT High Impact + ADDEDDATE + 2023-12-18 POWERSHELLEQUIVALENT Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSecurityGroupUsers.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSecurityGroupUsers.ps1 index 8f8643dacadc..0912dbce54bd 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSecurityGroupUsers.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSecurityGroupUsers.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardDisableSecurityGroupUsers { ADDEDCOMPONENT IMPACT Medium Impact + ADDEDDATE + 2022-07-17 POWERSHELLEQUIVALENT Update-MgBetaPolicyAuthorizationPolicy RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSelfServiceLicenses.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSelfServiceLicenses.ps1 index 64eab6788d6a..6829d04564ab 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSelfServiceLicenses.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSelfServiceLicenses.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardDisableSelfServiceLicenses { {"type":"textField","name":"standards.DisableSelfServiceLicenses.Exclusions","label":"License Ids to exclude from this standard","required":false} IMPACT Medium Impact + ADDEDDATE + 2021-11-16 POWERSHELLEQUIVALENT Set-MsolCompanySettings -AllowAdHocSubscriptions \$false RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharePointLegacyAuth.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharePointLegacyAuth.ps1 index a9e5d0d8c51c..f38bc79e6637 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharePointLegacyAuth.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharePointLegacyAuth.ps1 @@ -18,6 +18,8 @@ function Invoke-CIPPStandardDisableSharePointLegacyAuth { ADDEDCOMPONENT IMPACT Medium Impact + ADDEDDATE + 2024-02-05 POWERSHELLEQUIVALENT Set-SPOTenant -LegacyAuthProtocolsEnabled \$false RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharedMailbox.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharedMailbox.ps1 index b3825fe36b83..071a8d12d38e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharedMailbox.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharedMailbox.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardDisableSharedMailbox { ADDEDCOMPONENT IMPACT Medium Impact + ADDEDDATE + 2021-11-16 POWERSHELLEQUIVALENT Get-Mailbox & Update-MgUser RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 index 293ce18f7762..450882ec1bbe 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardDisableTNEF { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2024-04-26 POWERSHELLEQUIVALENT Set-RemoteDomain -Identity 'Default' -TNEFEnabled \$false RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTenantCreation.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTenantCreation.ps1 index a167603091de..34192ba11dd3 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTenantCreation.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTenantCreation.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardDisableTenantCreation { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2022-11-29 POWERSHELLEQUIVALENT Update-MgPolicyAuthorizationPolicy RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 index 442a48ad6c2f..d437a3780e50 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardDisableUserSiteCreate { ADDEDCOMPONENT IMPACT High Impact + ADDEDDATE + 2022-06-15 POWERSHELLEQUIVALENT Update-MgAdminSharePointSetting RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableViva.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableViva.ps1 index ac7b6b207575..b09e560e43c9 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableViva.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableViva.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardDisableViva { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2022-05-25 POWERSHELLEQUIVALENT Set-UserBriefingConfig RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableVoice.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableVoice.ps1 index db80a2e91e8e..b892cf34202e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableVoice.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableVoice.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardDisableVoice { ADDEDCOMPONENT IMPACT High Impact + ADDEDDATE + 2023-12-18 POWERSHELLEQUIVALENT Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisablex509Certificate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisablex509Certificate.ps1 index d6fcb84c2d08..b07f36a401af 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisablex509Certificate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisablex509Certificate.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardDisablex509Certificate { ADDEDCOMPONENT IMPACT High Impact + ADDEDDATE + 2023-12-18 POWERSHELLEQUIVALENT Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 index d2ab1cf7088d..224b1e81963f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 @@ -19,6 +19,8 @@ function Invoke-CIPPStandardEXODisableAutoForwarding { ADDEDCOMPONENT IMPACT High Impact + ADDEDDATE + 2024-07-26 POWERSHELLEQUIVALENT Set-HostedOutboundSpamFilterPolicy -AutoForwardingMode 'Off' RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableAppConsentRequests.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableAppConsentRequests.ps1 index 7db52549e3dc..e82f0032a277 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableAppConsentRequests.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableAppConsentRequests.ps1 @@ -18,6 +18,8 @@ function Invoke-CIPPStandardEnableAppConsentRequests { {"type":"AdminRolesMultiSelect","label":"App Consent Reviewer Roles","name":"standards.EnableAppConsentRequests.ReviewerRoles"} IMPACT Low Impact + ADDEDDATE + 2023-11-27 POWERSHELLEQUIVALENT Update-MgPolicyAdminConsentRequestPolicy RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableCustomerLockbox.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableCustomerLockbox.ps1 index ef686a9cccb1..b64f8062db19 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableCustomerLockbox.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableCustomerLockbox.ps1 @@ -18,6 +18,8 @@ function Invoke-CIPPStandardEnableCustomerLockbox { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2024-01-08 POWERSHELLEQUIVALENT Set-OrganizationConfig -CustomerLockBoxEnabled \$true RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableFIDO2.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableFIDO2.ps1 index bed8799542aa..88e68f9581c9 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableFIDO2.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableFIDO2.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardEnableFIDO2 { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2022-12-08 POWERSHELLEQUIVALENT Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableHardwareOAuth.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableHardwareOAuth.ps1 index 811d20565c9f..f7a90138c7f3 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableHardwareOAuth.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableHardwareOAuth.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardEnableHardwareOAuth { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2023-12-18 POWERSHELLEQUIVALENT Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableLitigationHold.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableLitigationHold.ps1 index 549a0d8b1590..f872be29d6ef 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableLitigationHold.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableLitigationHold.ps1 @@ -1,77 +1,79 @@ -function Invoke-CIPPStandardEnableLitigationHold { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) EnableLitigationHold - .SYNOPSIS - (Label) Enable Litigation Hold for all users - .DESCRIPTION - (Helptext) Enables litigation hold for all UserMailboxes with a valid license. - (DocsDescription) Enables litigation hold for all UserMailboxes with a valid license. - .NOTES - CAT - Exchange Standards - TAG - ADDEDCOMPONENT - IMPACT - Low Impact - POWERSHELLEQUIVALENT - Set-Mailbox -LitigationHoldEnabled \$true - RECOMMENDEDBY - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/exchange-standards#low-impact - #> - - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'EnableLitigationHold' - - $MailboxesNoLitHold = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-Mailbox' -cmdparams @{ Filter = 'LitigationHoldEnabled -eq "False"' } | Where-Object { $_.PersistedCapabilities -contains 'BPOS_S_DlpAddOn' -or $_.PersistedCapabilities -contains 'BPOS_S_Enterprise' } - - If ($Settings.remediate -eq $true) { - - if ($null -eq $MailboxesNoLitHold) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Litigation Hold already enabled for all accounts' -sev Info - } else { - try { - $Request = $MailboxesNoLitHold | ForEach-Object { - @{ - CmdletInput = @{ - CmdletName = 'Set-Mailbox' - Parameters = @{ Identity = $_.UserPrincipalName; LitigationHoldEnabled = $true } - } - } - } - - $BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray @($Request) - $BatchResults | ForEach-Object { - if ($_.error) { - $ErrorMessage = Get-NormalizedError -Message $_.error - Write-Host "Failed to Enable Litigation Hold for $($_.Target). Error: $ErrorMessage" - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to Enable Litigation Hold for $($_.Target). Error: $ErrorMessage" -sev Error - } - } - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to Enable Litigation Hold for all accounts. Error: $ErrorMessage" -sev Error - } - } - - } - - if ($Settings.alert -eq $true) { - - if ($MailboxesNoLitHold) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Mailboxes without Litigation Hold: $($MailboxesNoLitHold.Count)" -sev Alert - } else { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'All mailboxes have Litigation Hold enabled' -sev Info - } - } - - if ($Settings.report -eq $true) { - $filtered = $MailboxesNoLitHold | Select-Object -Property UserPrincipalName - Add-CIPPBPAField -FieldName 'EnableLitHold' -FieldValue $filtered -StoreAs json -Tenant $Tenant - } -} +function Invoke-CIPPStandardEnableLitigationHold { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) EnableLitigationHold + .SYNOPSIS + (Label) Enable Litigation Hold for all users + .DESCRIPTION + (Helptext) Enables litigation hold for all UserMailboxes with a valid license. + (DocsDescription) Enables litigation hold for all UserMailboxes with a valid license. + .NOTES + CAT + Exchange Standards + TAG + ADDEDCOMPONENT + IMPACT + Low Impact + ADDEDDATE + 2024-06-25 + POWERSHELLEQUIVALENT + Set-Mailbox -LitigationHoldEnabled \$true + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/exchange-standards#low-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'EnableLitigationHold' + + $MailboxesNoLitHold = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-Mailbox' -cmdparams @{ Filter = 'LitigationHoldEnabled -eq "False"' } | Where-Object { $_.PersistedCapabilities -contains 'BPOS_S_DlpAddOn' -or $_.PersistedCapabilities -contains 'BPOS_S_Enterprise' } + + If ($Settings.remediate -eq $true) { + + if ($null -eq $MailboxesNoLitHold) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Litigation Hold already enabled for all accounts' -sev Info + } else { + try { + $Request = $MailboxesNoLitHold | ForEach-Object { + @{ + CmdletInput = @{ + CmdletName = 'Set-Mailbox' + Parameters = @{ Identity = $_.UserPrincipalName; LitigationHoldEnabled = $true } + } + } + } + + $BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray @($Request) + $BatchResults | ForEach-Object { + if ($_.error) { + $ErrorMessage = Get-NormalizedError -Message $_.error + Write-Host "Failed to Enable Litigation Hold for $($_.Target). Error: $ErrorMessage" + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to Enable Litigation Hold for $($_.Target). Error: $ErrorMessage" -sev Error + } + } + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to Enable Litigation Hold for all accounts. Error: $ErrorMessage" -sev Error + } + } + + } + + if ($Settings.alert -eq $true) { + + if ($MailboxesNoLitHold) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Mailboxes without Litigation Hold: $($MailboxesNoLitHold.Count)" -sev Alert + } else { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'All mailboxes have Litigation Hold enabled' -sev Info + } + } + + if ($Settings.report -eq $true) { + $filtered = $MailboxesNoLitHold | Select-Object -Property UserPrincipalName + Add-CIPPBPAField -FieldName 'EnableLitHold' -FieldValue $filtered -StoreAs json -Tenant $Tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 index 022142a0a3c0..f7fa667ef7e5 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 @@ -16,9 +16,11 @@ function Invoke-CIPPStandardEnableMailTips { "CIS" "exo_mailtipsenabled" ADDEDCOMPONENT - {"type":"number","name":"standards.EnableMailTips.MailTipsLargeAudienceThreshold","label":"Number of recipients to trigger the large audience MailTip (Default is 25)","placeholder":"Enter a profile name","default":25} + {"type":"number","name":"standards.EnableMailTips.MailTipsLargeAudienceThreshold","label":"Number of recipients to trigger the large audience MailTip (Default is 25)","placeholder":"Enter a profile name","defaultValue":25} IMPACT Low Impact + ADDEDDATE + 2024-01-14 POWERSHELLEQUIVALENT Set-OrganizationConfig RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 index ec82ce508ce8..e65bd27e986b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 @@ -18,6 +18,8 @@ function Invoke-CIPPStandardEnableMailboxAuditing { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2024-01-08 POWERSHELLEQUIVALENT Set-OrganizationConfig -AuditDisabled \$false RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 index 8c26ecb9ef1e..32d76c87d284 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardEnableOnlineArchiving { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2024-01-20 POWERSHELLEQUIVALENT Enable-Mailbox -Archive \$true RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnablePronouns.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnablePronouns.ps1 index 532c133fc736..1023eecb109e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnablePronouns.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnablePronouns.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardEnablePronouns { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2024-06-05 POWERSHELLEQUIVALENT Update-MgBetaAdminPeoplePronoun -IsEnabledInOrganization:\$true RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 index c2b6154f2d99..93fcf7958b3e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardExcludedfileExt { {"type":"textField","name":"standards.ExcludedfileExt.ext","label":"Extensions, Comma separated"} IMPACT High Impact + ADDEDDATE + 2022-06-15 POWERSHELLEQUIVALENT Update-MgAdminSharePointSetting RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 index 4525d093a6e2..6aa494364001 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardExternalMFATrusted { {"type":"autoComplete","multiple":false,"creatable":false,"label":"Select value","name":"standards.ExternalMFATrusted.state","options":[{"label":"Enabled","value":"true"},{"label":"Disabled","value":"false"}]} IMPACT Low Impact + ADDEDDATE + 2024-03-26 POWERSHELLEQUIVALENT Update-MgBetaPolicyCrossTenantAccessPolicyDefault RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 index 652a5ab72466..34aa1a51fe1d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardFocusedInbox { {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.FocusedInbox.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} IMPACT Low Impact + ADDEDDATE + 2024-04-26 POWERSHELLEQUIVALENT Set-OrganizationConfig -FocusedInboxOn \$true or \$false RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 index 882ef5efd6c6..1e973ef9daeb 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardGlobalQuarantineNotifications { {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.GlobalQuarantineNotifications.NotificationInterval","options":[{"label":"4 hours","value":"04:00:00"},{"label":"1 day/Daily","value":"1.00:00:00"},{"label":"7 days/Weekly","value":"7.00:00:00"}]} IMPACT Low Impact + ADDEDDATE + 2024-05-03 POWERSHELLEQUIVALENT Set-QuarantinePolicy -EndUserSpamNotificationFrequency RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 index 698f42063b2f..c36603c329b4 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 @@ -18,6 +18,8 @@ function Invoke-CIPPStandardGroupTemplate { IMPACT Medium Impact + ADDEDDATE + 2023-12-30 ADDEDCOMPONENT {"type":"autoComplete","name":"groupTemplate","label":"Select Group Template","api":{"url":"/api/ListGroupTemplates","labelField":"Displayname","valueField":"GUID","queryKey":"ListGroupTemplates"}} UPDATECOMMENTBLOCK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGuestInvite.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGuestInvite.ps1 index cb3d745d17e5..4119652649a9 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGuestInvite.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGuestInvite.ps1 @@ -1,76 +1,78 @@ -function Invoke-CIPPStandardGuestInvite { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) GuestInvite - .SYNOPSIS - (Label) Guest Invite setting - .DESCRIPTION - (Helptext) This setting controls who can invite guests to your directory to collaborate on resources secured by your company, such as SharePoint sites or Azure resources. - (DocsDescription) This setting controls who can invite guests to your directory to collaborate on resources secured by your company, such as SharePoint sites or Azure resources. - .NOTES - CAT - Entra (AAD) Standards - TAG - ADDEDCOMPONENT - {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Who can send invites?","name":"standards.GuestInvite.allowInvitesFrom","options":[{"label":"Everyone","value":"everyone"},{"label":"Admins, Guest inviters and All Members","value":"adminsGuestInvitersAndAllMembers"},{"label":"Admins and Guest inviters","value":"adminsAndGuestInviters"},{"label":"None","value":"none"}]} - IMPACT - Medium Impact - POWERSHELLEQUIVALENT - - RECOMMENDEDBY - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/entra-aad-standards#medium-impact - #> - - param($Tenant, $Settings) - - $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' -tenantid $Tenant - - # Input validation and value handling - $AllowInvitesFromValue = $Settings.allowInvitesFrom.value ?? $Settings.allowInvitesFrom - if (([string]::IsNullOrWhiteSpace($AllowInvitesFromValue) -or $AllowInvitesFromValue -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'GuestInvite: Invalid allowInvitesFrom parameter set' -sev Error - Return - } - - $StateIsCorrect = ($CurrentState.allowInvitesFrom -eq $AllowInvitesFromValue) - - if ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Guest Invite settings is already applied correctly.' -Sev Info - } else { - try { - $GraphRequest = @{ - tenantID = $Tenant - uri = 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' - AsApp = $false - Type = 'PATCH' - ContentType = 'application/json; charset=utf-8' - Body = [pscustomobject]@{ - allowInvitesFrom = $AllowInvitesFromValue - } | ConvertTo-Json -Compress - } - New-GraphPostRequest @GraphRequest - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Successfully updated Guest Invite setting to $AllowInvitesFromValue" -Sev Info - } catch { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to update Guest Invite setting to $AllowInvitesFromValue" -Sev Error -LogData $_ - } - } - } - - if ($Settings.alert -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'Guest Invite settings is enabled.' -sev Info - } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'Guest Invite settings is not enabled.' -sev Alert - } - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'GuestInvite' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant - } -} +function Invoke-CIPPStandardGuestInvite { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) GuestInvite + .SYNOPSIS + (Label) Guest Invite setting + .DESCRIPTION + (Helptext) This setting controls who can invite guests to your directory to collaborate on resources secured by your company, such as SharePoint sites or Azure resources. + (DocsDescription) This setting controls who can invite guests to your directory to collaborate on resources secured by your company, such as SharePoint sites or Azure resources. + .NOTES + CAT + Entra (AAD) Standards + TAG + ADDEDCOMPONENT + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Who can send invites?","name":"standards.GuestInvite.allowInvitesFrom","options":[{"label":"Everyone","value":"everyone"},{"label":"Admins, Guest inviters and All Members","value":"adminsGuestInvitersAndAllMembers"},{"label":"Admins and Guest inviters","value":"adminsAndGuestInviters"},{"label":"None","value":"none"}]} + IMPACT + Medium Impact + ADDEDDATE + 2024-11-12 + POWERSHELLEQUIVALENT + + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/entra-aad-standards#medium-impact + #> + + param($Tenant, $Settings) + + $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' -tenantid $Tenant + + # Input validation and value handling + $AllowInvitesFromValue = $Settings.allowInvitesFrom.value ?? $Settings.allowInvitesFrom + if (([string]::IsNullOrWhiteSpace($AllowInvitesFromValue) -or $AllowInvitesFromValue -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'GuestInvite: Invalid allowInvitesFrom parameter set' -sev Error + Return + } + + $StateIsCorrect = ($CurrentState.allowInvitesFrom -eq $AllowInvitesFromValue) + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Guest Invite settings is already applied correctly.' -Sev Info + } else { + try { + $GraphRequest = @{ + tenantID = $Tenant + uri = 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' + AsApp = $false + Type = 'PATCH' + ContentType = 'application/json; charset=utf-8' + Body = [pscustomobject]@{ + allowInvitesFrom = $AllowInvitesFromValue + } | ConvertTo-Json -Compress + } + New-GraphPostRequest @GraphRequest + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Successfully updated Guest Invite setting to $AllowInvitesFromValue" -Sev Info + } catch { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to update Guest Invite setting to $AllowInvitesFromValue" -Sev Error -LogData $_ + } + } + } + + if ($Settings.alert -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Guest Invite settings is enabled.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Guest Invite settings is not enabled.' -sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'GuestInvite' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 index 6340b7f3e0d1..9342c223041d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 @@ -1,77 +1,79 @@ -function Invoke-CIPPStandardIntuneComplianceSettings { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) IntuneComplianceSettings - .SYNOPSIS - (Label) Set Intune Compliance Settings - .DESCRIPTION - (Helptext) Sets the mark devices with no compliance policy assigned as compliance/non compliant and Compliance status validity period. - (DocsDescription) Sets the mark devices with no compliance policy assigned as compliance/non compliant and Compliance status validity period. - .NOTES - CAT - Intune Standards - TAG - ADDEDCOMPONENT - {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.IntuneComplianceSettings.secureByDefault","label":"Mark devices with no compliance policy as","options":[{"label":"Compliant","value":"false"},{"label":"Non-Compliant","value":"true"}]} - {"type":"number","name":"standards.IntuneComplianceSettings.deviceComplianceCheckinThresholdDays","label":"Compliance status validity period (days)"} - IMPACT - Low Impact - POWERSHELLEQUIVALENT - - RECOMMENDEDBY - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/intune-standards#low-impact - #> - - param($Tenant, $Settings) - - $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/deviceManagement/settings' -tenantid $Tenant - - if ($null -eq $Settings.deviceComplianceCheckinThresholdDays) { $Settings.deviceComplianceCheckinThresholdDays = $CurrentState.deviceComplianceCheckinThresholdDays } - $SecureByDefault = $Settings.secureByDefault.value ?? $Settings.secureByDefault - $StateIsCorrect = ($CurrentState.secureByDefault -eq $SecureByDefault) -and - ($CurrentState.deviceComplianceCheckinThresholdDays -eq $Settings.deviceComplianceCheckinThresholdDays) - - if ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'InTune Compliance settings is already applied correctly.' -Sev Info - } else { - try { - $GraphRequest = @{ - tenantID = $Tenant - uri = 'https://graph.microsoft.com/beta/deviceManagement' - AsApp = $true - Type = 'PATCH' - ContentType = 'application/json; charset=utf-8' - Body = [pscustomobject]@{ - settings = [pscustomobject]@{ - secureByDefault = $SecureByDefault - deviceComplianceCheckinThresholdDays = $Settings.deviceComplianceCheckinThresholdDays - } - } | ConvertTo-Json -Compress - } - New-GraphPostRequest @GraphRequest - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully updated InTune Compliance settings.' -Sev Info - } catch { - $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Failed to update InTune Compliance settings.' -Sev Error -LogData $ErrorMessage - } - } - } - - if ($Settings.alert -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'InTune Compliance settings is enabled.' -Sev Info - } else { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'InTune Compliance settings is not enabled.' -Sev Alert - } - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'IntuneComplianceSettings' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant - } -} +function Invoke-CIPPStandardIntuneComplianceSettings { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) IntuneComplianceSettings + .SYNOPSIS + (Label) Set Intune Compliance Settings + .DESCRIPTION + (Helptext) Sets the mark devices with no compliance policy assigned as compliance/non compliant and Compliance status validity period. + (DocsDescription) Sets the mark devices with no compliance policy assigned as compliance/non compliant and Compliance status validity period. + .NOTES + CAT + Intune Standards + TAG + ADDEDCOMPONENT + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.IntuneComplianceSettings.secureByDefault","label":"Mark devices with no compliance policy as","options":[{"label":"Compliant","value":"false"},{"label":"Non-Compliant","value":"true"}]} + {"type":"number","name":"standards.IntuneComplianceSettings.deviceComplianceCheckinThresholdDays","label":"Compliance status validity period (days)"} + IMPACT + Low Impact + ADDEDDATE + 2024-11-12 + POWERSHELLEQUIVALENT + + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/intune-standards#low-impact + #> + + param($Tenant, $Settings) + + $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/deviceManagement/settings' -tenantid $Tenant + + if ($null -eq $Settings.deviceComplianceCheckinThresholdDays) { $Settings.deviceComplianceCheckinThresholdDays = $CurrentState.deviceComplianceCheckinThresholdDays } + $SecureByDefault = $Settings.secureByDefault.value ?? $Settings.secureByDefault + $StateIsCorrect = ($CurrentState.secureByDefault -eq $SecureByDefault) -and + ($CurrentState.deviceComplianceCheckinThresholdDays -eq $Settings.deviceComplianceCheckinThresholdDays) + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'InTune Compliance settings is already applied correctly.' -Sev Info + } else { + try { + $GraphRequest = @{ + tenantID = $Tenant + uri = 'https://graph.microsoft.com/beta/deviceManagement' + AsApp = $true + Type = 'PATCH' + ContentType = 'application/json; charset=utf-8' + Body = [pscustomobject]@{ + settings = [pscustomobject]@{ + secureByDefault = $SecureByDefault + deviceComplianceCheckinThresholdDays = $Settings.deviceComplianceCheckinThresholdDays + } + } | ConvertTo-Json -Compress + } + New-GraphPostRequest @GraphRequest + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully updated InTune Compliance settings.' -Sev Info + } catch { + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Failed to update InTune Compliance settings.' -Sev Error -LogData $ErrorMessage + } + } + } + + if ($Settings.alert -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'InTune Compliance settings is enabled.' -Sev Info + } else { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'InTune Compliance settings is not enabled.' -Sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'IntuneComplianceSettings' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 index 0fd4635ec0cc..361073a2f21f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 @@ -18,10 +18,13 @@ function Invoke-CIPPStandardIntuneTemplate { IMPACT High Impact + ADDEDDATE + 2023-12-30 ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"creatable":false,"name":"TemplateList","label":"Select Intune Template","api":{"url":"/api/ListIntuneTemplates","labelField":"Displayname","valueField":"GUID","queryKey":"languages"}} {"name":"AssignTo","label":"Who should this template be assigned to?","type":"radio","options":[{"label":"Do not assign","value":"On"},{"label":"Assign to all users","value":"allLicensedUsers"},{"label":"Assign to all devices","value":"AllDevices"},{"label":"Assign to all users and devices","value":"AllDevicesAndUsers"},{"label":"Assign to Custom Group","value":"customGroup"}]} {"type":"textField","required":false,"name":"customGroup","label":"Enter the custom group name if you selected 'Assign to Custom Group'. Wildcards are allowed."} + {"name":"excludeGroup","label":"Exclude Groups","type":"textField","required":false,"helpText":"Enter the group name to exclude from the assignment. Wildcards are allowed."} UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardLegacyMFACleanup.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardLegacyMFACleanup.ps1 index 5715f6f16b9d..94409b104bbb 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardLegacyMFACleanup.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardLegacyMFACleanup.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardLegacyMFACleanup { ADDEDCOMPONENT IMPACT Medium Impact + ADDEDDATE + 2021-11-16 POWERSHELLEQUIVALENT Set-MsolUser -StrongAuthenticationRequirements \$null RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMDMScope.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMDMScope.ps1 index 81e588624756..c778a17d4d7b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMDMScope.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMDMScope.ps1 @@ -1,124 +1,126 @@ -function Invoke-CIPPStandardMDMScope { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) MDMScope - .SYNOPSIS - (Label) Configure MDM user scope - .DESCRIPTION - (Helptext) Configures the MDM user scope. This also sets the terms of use, discovery and compliance URL to default URLs. - (DocsDescription) Configures the MDM user scope. This also sets the terms of use URL, discovery URL and compliance URL to default values. - .NOTES - CAT - Intune Standards - TAG - ADDEDCOMPONENT - {"name":"appliesTo","label":"MDM User Scope?","type":"radio","options":[{"label":"All","value":"all"},{"label":"None","value":"none"},{"label":"Custom Group","value":"selected"}]} - {"type":"textField","name":"standards.MDMScope.customGroup","label":"Custom Group Name","required":false} - IMPACT - Low Impact - POWERSHELLEQUIVALENT - Graph API - RECOMMENDEDBY - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/intune-standards#low-impact - #> - - param($Tenant, $Settings) - - $CurrentInfo = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/policies/mobileDeviceManagementPolicies/0000000a-0000-0000-c000-000000000000?$expand=includedGroups' -tenantid $Tenant - - $StateIsCorrect = ($CurrentInfo.termsOfUseUrl -eq 'https://portal.manage.microsoft.com/TermsofUse.aspx') -and - ($CurrentInfo.discoveryUrl -eq 'https://enrollment.manage.microsoft.com/enrollmentserver/discovery.svc') -and - ($CurrentInfo.complianceUrl -eq 'https://portal.manage.microsoft.com/?portalAction=Compliance') -and - ($CurrentInfo.appliesTo -eq $Settings.appliesTo) -and - ($Settings.appliesTo -ne 'selected' -or ($CurrentInfo.includedGroups.displayName -contains $Settings.customGroup)) - - If ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'MDM Scope already correctly configured' -sev Info - } else { - $GraphParam = @{ - tenantid = $tenant - Uri = 'https://graph.microsoft.com/beta/policies/mobileDeviceManagementPolicies/0000000a-0000-0000-c000-000000000000' - ContentType = 'application/json; charset=utf-8' - asApp = $false - type = 'PATCH' - AddedHeaders = @{'Accept-Language' = 0 } - Body = @{ - 'termsOfUseUrl' = 'https://portal.manage.microsoft.com/TermsofUse.aspx' - 'discoveryUrl' = 'https://enrollment.manage.microsoft.com/enrollmentserver/discovery.svc' - 'complianceUrl' = 'https://portal.manage.microsoft.com/?portalAction=Compliance' - } | ConvertTo-Json - } - - try { - New-GraphPostRequest @GraphParam - Write-LogMessage -API 'Standards' -tenant $tenant -message 'Successfully configured MDM Scope' -sev Info - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to configure MDM Scope." -sev Error -LogData $ErrorMessage - } - - # Workaround for MDM Scope Assignment error: "Could not set MDM Scope for [TENANT]: Simultaneous patch requests on both the appliesTo and URL properties are currently not supported." - if ($Settings.appliesTo -ne 'selected') { - $GraphParam = @{ - tenantid = $tenant - Uri = 'https://graph.microsoft.com/beta/policies/mobileDeviceManagementPolicies/0000000a-0000-0000-c000-000000000000' - ContentType = 'application/json; charset=utf-8' - asApp = $false - type = 'PATCH' - AddedHeaders = @{'Accept-Language' = 0 } - Body = @{ - 'appliesTo' = $Settings.appliesTo - } | ConvertTo-Json - } - - try { - New-GraphPostRequest @GraphParam - Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully assigned $($Settings.appliesTo) to MDM Scope" -sev Info - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to assign $($Settings.appliesTo) to MDM Scope." -sev Error -LogData $ErrorMessage - } - } else { - $GroupID = (New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/groups?`$top=999&`$select=id,displayName&`$filter=displayName eq '$($Settings.customGroup)'" -tenantid $tenant -asApp $true).id - $GraphParam = @{ - tenantid = $tenant - Uri = 'https://graph.microsoft.com/beta/policies/mobileDeviceManagementPolicies/0000000a-0000-0000-c000-000000000000/includedGroups/$ref' - ContentType = 'application/json; charset=utf-8' - asApp = $false - type = 'POST' - AddedHeaders = @{'Accept-Language' = 0 } - Body = @{ - '@odata.id' = "https://graph.microsoft.com/odata/groups('$GroupID')" - } | ConvertTo-Json - } - - try { - New-GraphPostRequest @GraphParam - Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully assigned $($Settings.customGroup) to MDM Scope" -sev Info - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to assign $($Settings.customGroup) to MDM Scope" -sev Error -LogData $ErrorMessage - } - } - } - } - - if ($Settings.alert -eq $true -eq $true) { - if ($StateIsCorrect) { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'MDM Scope is correctly configured' -sev Info - } else { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'MDM Scope is not correctly configured' -sev Alert - } - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'MDMScope' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant - } - -} +function Invoke-CIPPStandardMDMScope { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) MDMScope + .SYNOPSIS + (Label) Configure MDM user scope + .DESCRIPTION + (Helptext) Configures the MDM user scope. This also sets the terms of use, discovery and compliance URL to default URLs. + (DocsDescription) Configures the MDM user scope. This also sets the terms of use URL, discovery URL and compliance URL to default values. + .NOTES + CAT + Intune Standards + TAG + ADDEDCOMPONENT + {"name":"appliesTo","label":"MDM User Scope?","type":"radio","options":[{"label":"All","value":"all"},{"label":"None","value":"none"},{"label":"Custom Group","value":"selected"}]} + {"type":"textField","name":"standards.MDMScope.customGroup","label":"Custom Group Name","required":false} + IMPACT + Low Impact + ADDEDDATE + 2025-02-18 + POWERSHELLEQUIVALENT + Graph API + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/intune-standards#low-impact + #> + + param($Tenant, $Settings) + + $CurrentInfo = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/policies/mobileDeviceManagementPolicies/0000000a-0000-0000-c000-000000000000?$expand=includedGroups' -tenantid $Tenant + + $StateIsCorrect = ($CurrentInfo.termsOfUseUrl -eq 'https://portal.manage.microsoft.com/TermsofUse.aspx') -and + ($CurrentInfo.discoveryUrl -eq 'https://enrollment.manage.microsoft.com/enrollmentserver/discovery.svc') -and + ($CurrentInfo.complianceUrl -eq 'https://portal.manage.microsoft.com/?portalAction=Compliance') -and + ($CurrentInfo.appliesTo -eq $Settings.appliesTo) -and + ($Settings.appliesTo -ne 'selected' -or ($CurrentInfo.includedGroups.displayName -contains $Settings.customGroup)) + + If ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'MDM Scope already correctly configured' -sev Info + } else { + $GraphParam = @{ + tenantid = $tenant + Uri = 'https://graph.microsoft.com/beta/policies/mobileDeviceManagementPolicies/0000000a-0000-0000-c000-000000000000' + ContentType = 'application/json; charset=utf-8' + asApp = $false + type = 'PATCH' + AddedHeaders = @{'Accept-Language' = 0 } + Body = @{ + 'termsOfUseUrl' = 'https://portal.manage.microsoft.com/TermsofUse.aspx' + 'discoveryUrl' = 'https://enrollment.manage.microsoft.com/enrollmentserver/discovery.svc' + 'complianceUrl' = 'https://portal.manage.microsoft.com/?portalAction=Compliance' + } | ConvertTo-Json + } + + try { + New-GraphPostRequest @GraphParam + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Successfully configured MDM Scope' -sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to configure MDM Scope." -sev Error -LogData $ErrorMessage + } + + # Workaround for MDM Scope Assignment error: "Could not set MDM Scope for [TENANT]: Simultaneous patch requests on both the appliesTo and URL properties are currently not supported." + if ($Settings.appliesTo -ne 'selected') { + $GraphParam = @{ + tenantid = $tenant + Uri = 'https://graph.microsoft.com/beta/policies/mobileDeviceManagementPolicies/0000000a-0000-0000-c000-000000000000' + ContentType = 'application/json; charset=utf-8' + asApp = $false + type = 'PATCH' + AddedHeaders = @{'Accept-Language' = 0 } + Body = @{ + 'appliesTo' = $Settings.appliesTo + } | ConvertTo-Json + } + + try { + New-GraphPostRequest @GraphParam + Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully assigned $($Settings.appliesTo) to MDM Scope" -sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to assign $($Settings.appliesTo) to MDM Scope." -sev Error -LogData $ErrorMessage + } + } else { + $GroupID = (New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/groups?`$top=999&`$select=id,displayName&`$filter=displayName eq '$($Settings.customGroup)'" -tenantid $tenant -asApp $true).id + $GraphParam = @{ + tenantid = $tenant + Uri = 'https://graph.microsoft.com/beta/policies/mobileDeviceManagementPolicies/0000000a-0000-0000-c000-000000000000/includedGroups/$ref' + ContentType = 'application/json; charset=utf-8' + asApp = $false + type = 'POST' + AddedHeaders = @{'Accept-Language' = 0 } + Body = @{ + '@odata.id' = "https://graph.microsoft.com/odata/groups('$GroupID')" + } | ConvertTo-Json + } + + try { + New-GraphPostRequest @GraphParam + Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully assigned $($Settings.customGroup) to MDM Scope" -sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to assign $($Settings.customGroup) to MDM Scope" -sev Error -LogData $ErrorMessage + } + } + } + } + + if ($Settings.alert -eq $true -eq $true) { + if ($StateIsCorrect) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'MDM Scope is correctly configured' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'MDM Scope is not correctly configured' -sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'MDMScope' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant + } + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMailContacts.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMailContacts.ps1 index e62f75091cdc..bdff96e5f284 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMailContacts.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMailContacts.ps1 @@ -20,6 +20,8 @@ function Invoke-CIPPStandardMailContacts { {"type":"textField","name":"standards.MailContacts.TechContact","label":"Technical Contact","required":false} IMPACT Low Impact + ADDEDDATE + 2022-03-13 POWERSHELLEQUIVALENT Set-MsolCompanyContactInformation RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 index 16deab23d1b5..0ef4dda2994a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 @@ -1,171 +1,173 @@ -function Invoke-CIPPStandardMalwareFilterPolicy { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) MalwareFilterPolicy - .SYNOPSIS - (Label) Default Malware Filter Policy - .DESCRIPTION - (Helptext) This creates a Malware filter policy that enables the default File filter and Zero-hour auto purge for malware. - (DocsDescription) This creates a Malware filter policy that enables the default File filter and Zero-hour auto purge for malware. - .NOTES - CAT - Defender Standards - TAG - "CIS" - "mdo_zapspam" - "mdo_zapphish" - "mdo_zapmalware" - ADDEDCOMPONENT - {"type":"select","multiple":false,"label":"FileTypeAction","name":"standards.MalwareFilterPolicy.FileTypeAction","options":[{"label":"Reject","value":"Reject"},{"label":"Quarantine the message","value":"Quarantine"}]} - {"type":"textField","name":"standards.MalwareFilterPolicy.OptionalFileTypes","required":false,"label":"Optional File Types, Comma separated"} - {"type":"select","multiple":false,"label":"QuarantineTag","name":"standards.MalwareFilterPolicy.QuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} - {"type":"switch","label":"Enable Internal Sender Admin Notifications","required":false,"name":"standards.MalwareFilterPolicy.EnableInternalSenderAdminNotifications"} - {"type":"textField","name":"standards.MalwareFilterPolicy.InternalSenderAdminAddress","required":false,"label":"Internal Sender Admin Address"} - {"type":"switch","label":"Enable External Sender Admin Notifications","required":false,"name":"standards.MalwareFilterPolicy.EnableExternalSenderAdminNotifications"} - {"type":"textField","name":"standards.MalwareFilterPolicy.ExternalSenderAdminAddress","required":false,"label":"External Sender Admin Address"} - IMPACT - Low Impact - POWERSHELLEQUIVALENT - Set-MalwareFilterPolicy or New-MalwareFilterPolicy - RECOMMENDEDBY - "CIS" - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/defender-standards#low-impact - #> - - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'MalwareFilterPolicy' - - $PolicyList = @('CIPP Default Malware Policy','Default Malware Policy') - $ExistingPolicy = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-MalwareFilterPolicy' | Where-Object -Property Name -In $PolicyList - if ($null -eq $ExistingPolicy.Name) { - $PolicyName = $PolicyList[0] - } else { - $PolicyName = $ExistingPolicy.Name - } - $RuleList = @( 'CIPP Default Malware Rule','CIPP Default Malware Policy') - $ExistingRule = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-MalwareFilterRule' | Where-Object -Property Name -In $RuleList - if ($null -eq $ExistingRule.Name) { - $RuleName = $RuleList[0] - } else { - $RuleName = $ExistingRule.Name - } - - $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-MalwareFilterPolicy' | - Where-Object -Property Name -EQ $PolicyName | - Select-Object Name, EnableFileFilter, FileTypeAction, FileTypes, ZapEnabled, QuarantineTag, EnableInternalSenderAdminNotifications, InternalSenderAdminAddress, EnableExternalSenderAdminNotifications, ExternalSenderAdminAddress - - $DefaultFileTypes = @('ace', 'ani', 'apk', 'app', 'appx', 'arj', 'bat', 'cab', 'cmd', 'com', 'deb', 'dex', 'dll', 'docm', 'elf', 'exe', 'hta', 'img', 'iso', 'jar', 'jnlp', 'kext', 'lha', 'lib', 'library', 'lnk', 'lzh', 'macho', 'msc', 'msi', 'msix', 'msp', 'mst', 'pif', 'ppa', 'ppam', 'reg', 'rev', 'scf', 'scr', 'sct', 'sys', 'uif', 'vb', 'vbe', 'vbs', 'vxd', 'wsc', 'wsf', 'wsh', 'xll', 'xz', 'z') - - if ($null -eq $Settings.OptionalFileTypes) { - $ExpectedFileTypes = $DefaultFileTypes - } else { - $ExpectedFileTypes = $DefaultFileTypes + @($Settings.OptionalFileTypes.Split(',').Trim()) - } - - $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and - ($CurrentState.EnableFileFilter -eq $true) -and - ($CurrentState.FileTypeAction -eq $Settings.FileTypeAction) -and - (!(Compare-Object -ReferenceObject $CurrentState.FileTypes -DifferenceObject $ExpectedFileTypes)) -and - ($CurrentState.ZapEnabled -eq $true) -and - ($CurrentState.QuarantineTag -eq $Settings.QuarantineTag) -and - ($CurrentState.EnableInternalSenderAdminNotifications -eq $Settings.EnableInternalSenderAdminNotifications) -and - (($null -eq $Settings.InternalSenderAdminAddress) -or ($CurrentState.InternalSenderAdminAddress -eq $Settings.InternalSenderAdminAddress)) -and - ($CurrentState.EnableExternalSenderAdminNotifications -eq $Settings.EnableExternalSenderAdminNotifications) -and - (($null -eq $Settings.ExternalSenderAdminAddress) -or ($CurrentState.ExternalSenderAdminAddress -eq $Settings.ExternalSenderAdminAddress)) - - $AcceptedDomains = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AcceptedDomain' - - $RuleState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-MalwareFilterRule' | - Where-Object -Property Name -EQ $RuleName | - Select-Object Name, MalwareFilterPolicy, Priority, RecipientDomainIs - - $RuleStateIsCorrect = ($RuleState.Name -eq $RuleName) -and - ($RuleState.MalwareFilterPolicy -eq $PolicyName) -and - ($RuleState.Priority -eq 0) -and - (!(Compare-Object -ReferenceObject $RuleState.RecipientDomainIs -DifferenceObject $AcceptedDomains.Name)) - - if ($Settings.remediate -eq $true) { - - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Malware Filter Policy already correctly configured' -sev Info - } else { - $cmdparams = @{ - EnableFileFilter = $true - FileTypes = $ExpectedFileTypes - FileTypeAction = $Settings.FileTypeAction - ZapEnabled = $true - QuarantineTag = $Settings.QuarantineTag - EnableInternalSenderAdminNotifications = $Settings.EnableInternalSenderAdminNotifications - InternalSenderAdminAddress = $Settings.InternalSenderAdminAddress - EnableExternalSenderAdminNotifications = $Settings.EnableExternalSenderAdminNotifications - ExternalSenderAdminAddress = $Settings.ExternalSenderAdminAddress - } - - if ($CurrentState.Name -eq $PolicyName) { - try { - $cmdparams.Add('Identity', $PolicyName) - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-MalwareFilterPolicy' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Malware Filter policy $PolicyName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update Malware Filter policy $PolicyName." -sev Error -LogData $_ - } - } else { - try { - $cmdparams.Add('Name', $PolicyName) - New-ExoRequest -tenantid $Tenant -cmdlet 'New-MalwareFilterPolicy' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created Malware Filter policy $PolicyName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Malware Filter policy $PolicyName." -sev Error -LogData $_ - } - } - } - - if ($RuleStateIsCorrect -eq $false) { - $cmdparams = @{ - Priority = 0 - RecipientDomainIs = $AcceptedDomains.Name - } - - if ($RuleState.MalwareFilterPolicy -ne $PolicyName) { - $cmdparams.Add('MalwareFilterPolicy', $PolicyName) - } - - if ($RuleState.Name -eq $RuleName) { - try { - $cmdparams.Add('Identity', $RuleName) - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-MalwareFilterRule' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Malware Filter rule $RuleName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update Malware Filter Rule $RuleName." -sev Error -LogData $_ - } - } else { - try { - $cmdparams.Add('Name', $RuleName) - New-ExoRequest -tenantid $Tenant -cmdlet 'New-MalwareFilterRule' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created Malware Filter rule $RuleName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Malware Filter rule $RuleName." -sev Error -LogData $_ - } - } - } - } - - if ($Settings.alert -eq $true) { - - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Malware Filter Policy is enabled' -sev Info - } else { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Malware Filter Policy is not enabled' -sev Alert - } - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'MalwareFilterPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant - } - -} +function Invoke-CIPPStandardMalwareFilterPolicy { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) MalwareFilterPolicy + .SYNOPSIS + (Label) Default Malware Filter Policy + .DESCRIPTION + (Helptext) This creates a Malware filter policy that enables the default File filter and Zero-hour auto purge for malware. + (DocsDescription) This creates a Malware filter policy that enables the default File filter and Zero-hour auto purge for malware. + .NOTES + CAT + Defender Standards + TAG + "CIS" + "mdo_zapspam" + "mdo_zapphish" + "mdo_zapmalware" + ADDEDCOMPONENT + {"type":"select","multiple":false,"label":"FileTypeAction","name":"standards.MalwareFilterPolicy.FileTypeAction","options":[{"label":"Reject","value":"Reject"},{"label":"Quarantine the message","value":"Quarantine"}]} + {"type":"textField","name":"standards.MalwareFilterPolicy.OptionalFileTypes","required":false,"label":"Optional File Types, Comma separated"} + {"type":"select","multiple":false,"label":"QuarantineTag","name":"standards.MalwareFilterPolicy.QuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} + {"type":"switch","label":"Enable Internal Sender Admin Notifications","required":false,"name":"standards.MalwareFilterPolicy.EnableInternalSenderAdminNotifications"} + {"type":"textField","name":"standards.MalwareFilterPolicy.InternalSenderAdminAddress","required":false,"label":"Internal Sender Admin Address"} + {"type":"switch","label":"Enable External Sender Admin Notifications","required":false,"name":"standards.MalwareFilterPolicy.EnableExternalSenderAdminNotifications"} + {"type":"textField","name":"standards.MalwareFilterPolicy.ExternalSenderAdminAddress","required":false,"label":"External Sender Admin Address"} + IMPACT + Low Impact + ADDEDDATE + 2024-03-25 + POWERSHELLEQUIVALENT + Set-MalwareFilterPolicy or New-MalwareFilterPolicy + RECOMMENDEDBY + "CIS" + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/defender-standards#low-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'MalwareFilterPolicy' + + $PolicyList = @('CIPP Default Malware Policy','Default Malware Policy') + $ExistingPolicy = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-MalwareFilterPolicy' | Where-Object -Property Name -In $PolicyList + if ($null -eq $ExistingPolicy.Name) { + $PolicyName = $PolicyList[0] + } else { + $PolicyName = $ExistingPolicy.Name + } + $RuleList = @( 'CIPP Default Malware Rule','CIPP Default Malware Policy') + $ExistingRule = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-MalwareFilterRule' | Where-Object -Property Name -In $RuleList + if ($null -eq $ExistingRule.Name) { + $RuleName = $RuleList[0] + } else { + $RuleName = $ExistingRule.Name + } + + $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-MalwareFilterPolicy' | + Where-Object -Property Name -EQ $PolicyName | + Select-Object Name, EnableFileFilter, FileTypeAction, FileTypes, ZapEnabled, QuarantineTag, EnableInternalSenderAdminNotifications, InternalSenderAdminAddress, EnableExternalSenderAdminNotifications, ExternalSenderAdminAddress + + $DefaultFileTypes = @('ace', 'ani', 'apk', 'app', 'appx', 'arj', 'bat', 'cab', 'cmd', 'com', 'deb', 'dex', 'dll', 'docm', 'elf', 'exe', 'hta', 'img', 'iso', 'jar', 'jnlp', 'kext', 'lha', 'lib', 'library', 'lnk', 'lzh', 'macho', 'msc', 'msi', 'msix', 'msp', 'mst', 'pif', 'ppa', 'ppam', 'reg', 'rev', 'scf', 'scr', 'sct', 'sys', 'uif', 'vb', 'vbe', 'vbs', 'vxd', 'wsc', 'wsf', 'wsh', 'xll', 'xz', 'z') + + if ($null -eq $Settings.OptionalFileTypes) { + $ExpectedFileTypes = $DefaultFileTypes + } else { + $ExpectedFileTypes = $DefaultFileTypes + @($Settings.OptionalFileTypes.Split(',').Trim()) + } + + $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and + ($CurrentState.EnableFileFilter -eq $true) -and + ($CurrentState.FileTypeAction -eq $Settings.FileTypeAction) -and + (!(Compare-Object -ReferenceObject $CurrentState.FileTypes -DifferenceObject $ExpectedFileTypes)) -and + ($CurrentState.ZapEnabled -eq $true) -and + ($CurrentState.QuarantineTag -eq $Settings.QuarantineTag) -and + ($CurrentState.EnableInternalSenderAdminNotifications -eq $Settings.EnableInternalSenderAdminNotifications) -and + (($null -eq $Settings.InternalSenderAdminAddress) -or ($CurrentState.InternalSenderAdminAddress -eq $Settings.InternalSenderAdminAddress)) -and + ($CurrentState.EnableExternalSenderAdminNotifications -eq $Settings.EnableExternalSenderAdminNotifications) -and + (($null -eq $Settings.ExternalSenderAdminAddress) -or ($CurrentState.ExternalSenderAdminAddress -eq $Settings.ExternalSenderAdminAddress)) + + $AcceptedDomains = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AcceptedDomain' + + $RuleState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-MalwareFilterRule' | + Where-Object -Property Name -EQ $RuleName | + Select-Object Name, MalwareFilterPolicy, Priority, RecipientDomainIs + + $RuleStateIsCorrect = ($RuleState.Name -eq $RuleName) -and + ($RuleState.MalwareFilterPolicy -eq $PolicyName) -and + ($RuleState.Priority -eq 0) -and + (!(Compare-Object -ReferenceObject $RuleState.RecipientDomainIs -DifferenceObject $AcceptedDomains.Name)) + + if ($Settings.remediate -eq $true) { + + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Malware Filter Policy already correctly configured' -sev Info + } else { + $cmdparams = @{ + EnableFileFilter = $true + FileTypes = $ExpectedFileTypes + FileTypeAction = $Settings.FileTypeAction + ZapEnabled = $true + QuarantineTag = $Settings.QuarantineTag + EnableInternalSenderAdminNotifications = $Settings.EnableInternalSenderAdminNotifications + InternalSenderAdminAddress = $Settings.InternalSenderAdminAddress + EnableExternalSenderAdminNotifications = $Settings.EnableExternalSenderAdminNotifications + ExternalSenderAdminAddress = $Settings.ExternalSenderAdminAddress + } + + if ($CurrentState.Name -eq $PolicyName) { + try { + $cmdparams.Add('Identity', $PolicyName) + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-MalwareFilterPolicy' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Malware Filter policy $PolicyName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update Malware Filter policy $PolicyName." -sev Error -LogData $_ + } + } else { + try { + $cmdparams.Add('Name', $PolicyName) + New-ExoRequest -tenantid $Tenant -cmdlet 'New-MalwareFilterPolicy' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created Malware Filter policy $PolicyName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Malware Filter policy $PolicyName." -sev Error -LogData $_ + } + } + } + + if ($RuleStateIsCorrect -eq $false) { + $cmdparams = @{ + Priority = 0 + RecipientDomainIs = $AcceptedDomains.Name + } + + if ($RuleState.MalwareFilterPolicy -ne $PolicyName) { + $cmdparams.Add('MalwareFilterPolicy', $PolicyName) + } + + if ($RuleState.Name -eq $RuleName) { + try { + $cmdparams.Add('Identity', $RuleName) + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-MalwareFilterRule' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Malware Filter rule $RuleName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update Malware Filter Rule $RuleName." -sev Error -LogData $_ + } + } else { + try { + $cmdparams.Add('Name', $RuleName) + New-ExoRequest -tenantid $Tenant -cmdlet 'New-MalwareFilterRule' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created Malware Filter rule $RuleName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Malware Filter rule $RuleName." -sev Error -LogData $_ + } + } + } + } + + if ($Settings.alert -eq $true) { + + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Malware Filter Policy is enabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Malware Filter Policy is not enabled' -sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'MalwareFilterPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant + } + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMessageExpiration.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMessageExpiration.ps1 index b79ae37cebe4..22da3819e8f9 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMessageExpiration.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMessageExpiration.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardMessageExpiration { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2024-02-23 POWERSHELLEQUIVALENT Set-TransportConfig -MessageExpirationTimeout 12.00:00:00 RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 index 1def2f369951..b97689a2f960 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardNudgeMFA.ps1 @@ -15,9 +15,11 @@ function Invoke-CIPPStandardNudgeMFA { TAG ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"creatable":false,"label":"Select value","name":"standards.NudgeMFA.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} - {"type":"number","name":"standards.NudgeMFA.snoozeDurationInDays","label":"Number of days to allow users to skip registering Authenticator (0-14, default is 1)","default":1} + {"type":"number","name":"standards.NudgeMFA.snoozeDurationInDays","label":"Number of days to allow users to skip registering Authenticator (0-14, default is 1)","defaultValue":1} IMPACT Low Impact + ADDEDDATE + 2022-12-08 POWERSHELLEQUIVALENT Update-MgPolicyAuthenticationMethodPolicy RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 index 275f4b6dcf03..c1bdb39fa96b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 @@ -18,6 +18,8 @@ function Invoke-CIPPStandardOauthConsent { {"type":"textField","name":"standards.OauthConsent.AllowedApps","label":"Allowed application IDs, comma separated","required":false} IMPACT Medium Impact + ADDEDDATE + 2021-11-16 POWERSHELLEQUIVALENT Update-MgPolicyAuthorizationPolicy RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsentLowSec.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsentLowSec.ps1 index 4573a7875eeb..9ab97150d1e3 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsentLowSec.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsentLowSec.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardOauthConsentLowSec { "IntegratedApps" IMPACT Medium Impact + ADDEDDATE + 2022-08-16 POWERSHELLEQUIVALENT Update-MgPolicyAuthorizationPolicy RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOutBoundSpamAlert.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOutBoundSpamAlert.ps1 index 695f9f5e7759..098a85d27f3e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOutBoundSpamAlert.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOutBoundSpamAlert.ps1 @@ -18,6 +18,8 @@ function Invoke-CIPPStandardOutBoundSpamAlert { {"type":"textField","name":"standards.OutBoundSpamAlert.OutboundSpamContact","label":"Outbound spam contact"} IMPACT Low Impact + ADDEDDATE + 2023-05-03 POWERSHELLEQUIVALENT Set-HostedOutboundSpamFilterPolicy RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 index e21c27e1fe7c..f7efdc7d203c 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardPWcompanionAppAllowedState { {"type":"autoComplete","multiple":false,"creatable":false,"label":"Select value","name":"standards.PWcompanionAppAllowedState.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} IMPACT Low Impact + ADDEDDATE + 2023-05-18 POWERSHELLEQUIVALENT Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 index 87e717b10887..142732c5b0cf 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWdisplayAppInformationRequiredState.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardPWdisplayAppInformationRequiredState { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2021-11-16 POWERSHELLEQUIVALENT Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 index c629902a52b0..f21def0d2784 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 @@ -18,6 +18,8 @@ function Invoke-CIPPStandardPasswordExpireDisabled { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2021-11-16 POWERSHELLEQUIVALENT Update-MgDomain RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPerUserMFA.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPerUserMFA.ps1 index 8df7ac45f4e5..8e028d5a4eaa 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPerUserMFA.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPerUserMFA.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardPerUserMFA { ADDEDCOMPONENT IMPACT High Impact + ADDEDDATE + 2024-06-14 POWERSHELLEQUIVALENT Graph API RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishProtection.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishProtection.ps1 index 33670894bd76..d250edcd3b66 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishProtection.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishProtection.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardPhishProtection { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2024-01-22 DISABLEDFEATURES POWERSHELLEQUIVALENT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardProfilePhotos.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardProfilePhotos.ps1 index 0453733541e6..9b8db4155929 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardProfilePhotos.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardProfilePhotos.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardProfilePhotos { {"type":"autoComplete","multiple":false,"creatable":false,"label":"Select value","name":"standards.ProfilePhotos.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} IMPACT Low Impact + ADDEDDATE + 2025-01-19 POWERSHELLEQUIVALENT Set-OrganizationConfig -ProfilePhotoOptions EnablePhotos and Update-MgBetaAdminPeople RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 index 8eafb2c45768..84a5376bb816 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 @@ -1,87 +1,89 @@ -function Invoke-CIPPStandardQuarantineRequestAlert { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) QuarantineRequestAlert - .SYNOPSIS - (Label) Quarantine Release Request Alert - .DESCRIPTION - (Helptext) Sets a e-mail address to alert when a User requests to release a quarantined message. - (DocsDescription) Sets a e-mail address to alert when a User requests to release a quarantined message. This is useful for monitoring and ensuring that the correct messages are released. - .NOTES - CAT - Defender Standards - TAG - ADDEDCOMPONENT - {"type":"textField","name":"standards.QuarantineRequestAlert.NotifyUser","label":"E-mail to receive the alert"} - IMPACT - Low Impact - POWERSHELLEQUIVALENT - New-ProtectionAlert and Set-ProtectionAlert - RECOMMENDEDBY - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/defender-standards#low-impact - #> - - param ($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'QuarantineRequestAlert' - - $PolicyName = 'CIPP User requested to release a quarantined message' - - $CurrentState = New-ExoRequest -TenantId $Tenant -cmdlet 'Get-ProtectionAlert' -Compliance | - Where-Object { $_.Name -eq $PolicyName } | - Select-Object -Property * - - $StateIsCorrect = ($CurrentState.NotifyUser -contains $Settings.NotifyUser) - - if ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Quarantine Request Alert is configured correctly' -sev Info - } else { - $cmdparams = @{ - 'NotifyUser' = $Settings.NotifyUser - 'Category' = 'ThreatManagement' - 'Operation' = 'QuarantineRequestReleaseMessage' - 'Severity' = 'Informational' - 'AggregationType' = 'None' - } - - if ($CurrentState.Name -eq $PolicyName) { - try { - $cmdparams['Identity'] = $PolicyName - New-ExoRequest -TenantId $Tenant -cmdlet 'Set-ProtectionAlert' -Compliance -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully configured Quarantine Request Alert' -sev Info - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to configure Quarantine Request Alert. Error: $ErrorMessage" -sev Error - } - } else { - try { - $cmdparams['name'] = $PolicyName - $cmdparams['ThreatType'] = 'Activity' - - New-ExoRequest -TenantId $Tenant -cmdlet 'New-ProtectionAlert' -Compliance -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully created Quarantine Request Alert' -sev Info - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to create Quarantine Request Alert. Error: $ErrorMessage" -sev Error - } - } - } - } - - if ($Settings.alert -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Quarantine Request Alert is enabled' -sev Info - } else { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Quarantine Request Alert is disabled' -sev Info - } - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'QuarantineRequestAlert' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant - } -} +function Invoke-CIPPStandardQuarantineRequestAlert { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) QuarantineRequestAlert + .SYNOPSIS + (Label) Quarantine Release Request Alert + .DESCRIPTION + (Helptext) Sets a e-mail address to alert when a User requests to release a quarantined message. + (DocsDescription) Sets a e-mail address to alert when a User requests to release a quarantined message. This is useful for monitoring and ensuring that the correct messages are released. + .NOTES + CAT + Defender Standards + TAG + ADDEDCOMPONENT + {"type":"textField","name":"standards.QuarantineRequestAlert.NotifyUser","label":"E-mail to receive the alert"} + IMPACT + Low Impact + ADDEDDATE + 2024-07-15 + POWERSHELLEQUIVALENT + New-ProtectionAlert and Set-ProtectionAlert + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/defender-standards#low-impact + #> + + param ($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'QuarantineRequestAlert' + + $PolicyName = 'CIPP User requested to release a quarantined message' + + $CurrentState = New-ExoRequest -TenantId $Tenant -cmdlet 'Get-ProtectionAlert' -Compliance | + Where-Object { $_.Name -eq $PolicyName } | + Select-Object -Property * + + $StateIsCorrect = ($CurrentState.NotifyUser -contains $Settings.NotifyUser) + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Quarantine Request Alert is configured correctly' -sev Info + } else { + $cmdparams = @{ + 'NotifyUser' = $Settings.NotifyUser + 'Category' = 'ThreatManagement' + 'Operation' = 'QuarantineRequestReleaseMessage' + 'Severity' = 'Informational' + 'AggregationType' = 'None' + } + + if ($CurrentState.Name -eq $PolicyName) { + try { + $cmdparams['Identity'] = $PolicyName + New-ExoRequest -TenantId $Tenant -cmdlet 'Set-ProtectionAlert' -Compliance -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully configured Quarantine Request Alert' -sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to configure Quarantine Request Alert. Error: $ErrorMessage" -sev Error + } + } else { + try { + $cmdparams['name'] = $PolicyName + $cmdparams['ThreatType'] = 'Activity' + + New-ExoRequest -TenantId $Tenant -cmdlet 'New-ProtectionAlert' -Compliance -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully created Quarantine Request Alert' -sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to create Quarantine Request Alert. Error: $ErrorMessage" -sev Error + } + } + } + } + + if ($Settings.alert -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Quarantine Request Alert is enabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Quarantine Request Alert is disabled' -sev Info + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'QuarantineRequestAlert' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 index 2e749da720f2..346b100e04c6 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardRetentionPolicyTag { {"type":"number","name":"standards.RetentionPolicyTag.AgeLimitForRetention","label":"Retention Days","required":true} IMPACT High Impact + ADDEDDATE + 2025-02-02 POWERSHELLEQUIVALENT Set-RetentionPolicyTag RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 index 71dd3abde10f..1421b89997b0 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardRotateDKIM { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2023-03-14 POWERSHELLEQUIVALENT Rotate-DkimSigningConfig RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPAzureB2B.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPAzureB2B.ps1 index 63a6e0d431cb..e447a74ab4af 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPAzureB2B.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPAzureB2B.ps1 @@ -1,67 +1,69 @@ -function Invoke-CIPPStandardSPAzureB2B { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) SPAzureB2B - .SYNOPSIS - (Label) Enable SharePoint and OneDrive integration with Azure AD B2B - .DESCRIPTION - (Helptext) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled - (DocsDescription) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled - .NOTES - CAT - SharePoint Standards - TAG - "CIS" - ADDEDCOMPONENT - IMPACT - Low Impact - POWERSHELLEQUIVALENT - Set-SPOTenant -EnableAzureADB2BIntegration \$true - RECOMMENDEDBY - "CIS 3.0" - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/sharepoint-standards#low-impact - #> - - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SPAzureB2B' - - $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | - Select-Object -Property EnableAzureADB2BIntegration - - $StateIsCorrect = ($CurrentState.EnableAzureADB2BIntegration -eq $true) - - if ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint Azure B2B is already enabled' -Sev Info - } else { - $Properties = @{ - EnableAzureADB2BIntegration = $true - } - - try { - Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully set the SharePoint Azure B2B to enabled' -Sev Info - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to set the SharePoint Azure B2B to enabled. Error: $ErrorMessage" -Sev Error - } - } - } - - if ($Settings.alert -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint Azure B2B is enabled' -Sev Info - } else { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint Azure B2B is not enabled' -Sev Alert - } - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'AzureB2B' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant - } -} +function Invoke-CIPPStandardSPAzureB2B { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) SPAzureB2B + .SYNOPSIS + (Label) Enable SharePoint and OneDrive integration with Azure AD B2B + .DESCRIPTION + (Helptext) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled + (DocsDescription) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled + .NOTES + CAT + SharePoint Standards + TAG + "CIS" + ADDEDCOMPONENT + IMPACT + Low Impact + ADDEDDATE + 2024-07-09 + POWERSHELLEQUIVALENT + Set-SPOTenant -EnableAzureADB2BIntegration \$true + RECOMMENDEDBY + "CIS 3.0" + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/sharepoint-standards#low-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SPAzureB2B' + + $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | + Select-Object -Property EnableAzureADB2BIntegration + + $StateIsCorrect = ($CurrentState.EnableAzureADB2BIntegration -eq $true) + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint Azure B2B is already enabled' -Sev Info + } else { + $Properties = @{ + EnableAzureADB2BIntegration = $true + } + + try { + Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully set the SharePoint Azure B2B to enabled' -Sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to set the SharePoint Azure B2B to enabled. Error: $ErrorMessage" -Sev Error + } + } + } + + if ($Settings.alert -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint Azure B2B is enabled' -Sev Info + } else { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint Azure B2B is not enabled' -Sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'AzureB2B' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDirectSharing.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDirectSharing.ps1 index ba1d39eef96e..9852c5536afb 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDirectSharing.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDirectSharing.ps1 @@ -1,68 +1,70 @@ -function Invoke-CIPPStandardSPDirectSharing { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) SPDirectSharing - .SYNOPSIS - (Label) Default sharing to Direct users - .DESCRIPTION - (Helptext) Ensure default link sharing is set to Direct in SharePoint and OneDrive - (DocsDescription) Ensure default link sharing is set to Direct in SharePoint and OneDrive - .NOTES - CAT - SharePoint Standards - TAG - "CIS" - ADDEDCOMPONENT - IMPACT - Medium Impact - POWERSHELLEQUIVALENT - Set-SPOTenant -DefaultSharingLinkType Direct - RECOMMENDEDBY - "CIS 3.0" - "CIPP" - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/sharepoint-standards#medium-impact - #> - - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SPDirectSharing' - - $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | - Select-Object -Property DefaultSharingLinkType - - $StateIsCorrect = ($CurrentState.DefaultSharingLinkType -eq 'Direct' -or $CurrentState.DefaultSharingLinkType -eq 1) - - if ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint Sharing Restriction is already enabled' -Sev Info - } else { - $Properties = @{ - DefaultSharingLinkType = 1 - } - - try { - Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully set the SharePoint Sharing Restriction to Direct' -Sev Info - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to set the SharePoint Sharing Restriction to Direct. Error: $ErrorMessage" -Sev Error - } - } - } - - if ($Settings.alert -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint Sharing Restriction is enabled' -Sev Info - } else { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint Sharing Restriction is not enabled' -Sev Alert - } - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'DirectSharing' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant - } -} +function Invoke-CIPPStandardSPDirectSharing { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) SPDirectSharing + .SYNOPSIS + (Label) Default sharing to Direct users + .DESCRIPTION + (Helptext) Ensure default link sharing is set to Direct in SharePoint and OneDrive + (DocsDescription) Ensure default link sharing is set to Direct in SharePoint and OneDrive + .NOTES + CAT + SharePoint Standards + TAG + "CIS" + ADDEDCOMPONENT + IMPACT + Medium Impact + ADDEDDATE + 2024-07-09 + POWERSHELLEQUIVALENT + Set-SPOTenant -DefaultSharingLinkType Direct + RECOMMENDEDBY + "CIS" + "CIPP" + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/sharepoint-standards#medium-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SPDirectSharing' + + $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | + Select-Object -Property DefaultSharingLinkType + + $StateIsCorrect = ($CurrentState.DefaultSharingLinkType -eq 'Direct' -or $CurrentState.DefaultSharingLinkType -eq 1) + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint Sharing Restriction is already enabled' -Sev Info + } else { + $Properties = @{ + DefaultSharingLinkType = 1 + } + + try { + Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully set the SharePoint Sharing Restriction to Direct' -Sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to set the SharePoint Sharing Restriction to Direct. Error: $ErrorMessage" -Sev Error + } + } + } + + if ($Settings.alert -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint Sharing Restriction is enabled' -Sev Info + } else { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint Sharing Restriction is not enabled' -Sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'DirectSharing' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisableLegacyWorkflows.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisableLegacyWorkflows.ps1 index 7dd4ab37ffa1..a4034f2c66aa 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisableLegacyWorkflows.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisableLegacyWorkflows.ps1 @@ -1,68 +1,70 @@ -function Invoke-CIPPStandardSPDisableLegacyWorkflows { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) SPDisableLegacyWorkflows - .SYNOPSIS - (Label) Disable Legacy Workflows - .DESCRIPTION - (Helptext) Disables the creation of new SharePoint 2010 and 2013 classic workflows and removes the 'Return to classic SharePoint' link on modern SharePoint list and library pages. - (DocsDescription) Disables the creation of new SharePoint 2010 and 2013 classic workflows and removes the 'Return to classic SharePoint' link on modern SharePoint list and library pages. - .NOTES - CAT - SharePoint Standards - TAG - ADDEDCOMPONENT - IMPACT - Low Impact - POWERSHELLEQUIVALENT - Set-SPOTenant -DisableWorkflow2010 \$true -DisableWorkflow2013 \$true -DisableBackToClassic \$true - RECOMMENDEDBY - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/sharepoint-standards#low-impact - #> - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SPDisableLegacyWorkflows' - - $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | - Select-Object -Property * - - $StateIsCorrect = ($CurrentState.StopNew2010Workflows -eq $true) -and - ($CurrentState.StopNew2013Workflows -eq $true) -and - ($CurrentState.DisableBackToClassic -eq $true) - - if ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Legacy Workflows are already disabled.' -Sev Info - } else { - $Properties = @{ - StopNew2010Workflows = $true - StopNew2013Workflows = $true - DisableBackToClassic = $true - } - - try { - Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully disabled Legacy Workflows' -Sev Info - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to disable Legacy Workflows. Error: $ErrorMessage" -Sev Error - } - } - } - - if ($Settings.alert -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Legacy Workflows are disabled' -Sev Info - } else { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Legacy Workflows are enabled' -Sev Info - } - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'SPDisableLegacyWorkflows' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant - } -} +function Invoke-CIPPStandardSPDisableLegacyWorkflows { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) SPDisableLegacyWorkflows + .SYNOPSIS + (Label) Disable Legacy Workflows + .DESCRIPTION + (Helptext) Disables the creation of new SharePoint 2010 and 2013 classic workflows and removes the 'Return to classic SharePoint' link on modern SharePoint list and library pages. + (DocsDescription) Disables the creation of new SharePoint 2010 and 2013 classic workflows and removes the 'Return to classic SharePoint' link on modern SharePoint list and library pages. + .NOTES + CAT + SharePoint Standards + TAG + ADDEDCOMPONENT + IMPACT + Low Impact + ADDEDDATE + 2024-07-15 + POWERSHELLEQUIVALENT + Set-SPOTenant -DisableWorkflow2010 \$true -DisableWorkflow2013 \$true -DisableBackToClassic \$true + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/sharepoint-standards#low-impact + #> + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SPDisableLegacyWorkflows' + + $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | + Select-Object -Property * + + $StateIsCorrect = ($CurrentState.StopNew2010Workflows -eq $true) -and + ($CurrentState.StopNew2013Workflows -eq $true) -and + ($CurrentState.DisableBackToClassic -eq $true) + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Legacy Workflows are already disabled.' -Sev Info + } else { + $Properties = @{ + StopNew2010Workflows = $true + StopNew2013Workflows = $true + DisableBackToClassic = $true + } + + try { + Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully disabled Legacy Workflows' -Sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to disable Legacy Workflows. Error: $ErrorMessage" -Sev Error + } + } + } + + if ($Settings.alert -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Legacy Workflows are disabled' -Sev Info + } else { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Legacy Workflows are enabled' -Sev Info + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'SPDisableLegacyWorkflows' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisallowInfectedFiles.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisallowInfectedFiles.ps1 index 0f2c2ecead49..03c34ec3b768 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisallowInfectedFiles.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisallowInfectedFiles.ps1 @@ -1,68 +1,70 @@ -function Invoke-CIPPStandardSPDisallowInfectedFiles { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) SPDisallowInfectedFiles - .SYNOPSIS - (Label) Disallow downloading infected files from SharePoint - .DESCRIPTION - (Helptext) Ensure Office 365 SharePoint infected files are disallowed for download - (DocsDescription) Ensure Office 365 SharePoint infected files are disallowed for download - .NOTES - CAT - SharePoint Standards - TAG - "CIS" - ADDEDCOMPONENT - IMPACT - Low Impact - POWERSHELLEQUIVALENT - Set-SPOTenant -DisallowInfectedFileDownload \$true - RECOMMENDEDBY - "CIS 3.0" - "CIPP" - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/sharepoint-standards#low-impact - #> - - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SPDisallowInfectedFiles' - - $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | - Select-Object -Property DisallowInfectedFileDownload - - $StateIsCorrect = ($CurrentState.DisallowInfectedFileDownload -eq $true) - - if ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $tenant -Message 'Downloading Sharepoint infected files are already disallowed.' -Sev Info - } else { - $Properties = @{ - DisallowInfectedFileDownload = $true - } - - try { - Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties - Write-LogMessage -API 'Standards' -tenant $tenant -Message 'Successfully disallowed downloading SharePoint infected files.' -Sev Info - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -Message "Failed to disallow downloading Sharepoint infected files. Error: $ErrorMessage" -Sev Error - } - } - } - - if ($Settings.alert -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $tenant -Message 'Downloading Sharepoint infected files are disallowed.' -Sev Info - } else { - Write-LogMessage -API 'Standards' -tenant $tenant -Message 'Downloading Sharepoint infected files are allowed.' -Sev Alert - } - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'SPDisallowInfectedFiles' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant - } -} +function Invoke-CIPPStandardSPDisallowInfectedFiles { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) SPDisallowInfectedFiles + .SYNOPSIS + (Label) Disallow downloading infected files from SharePoint + .DESCRIPTION + (Helptext) Ensure Office 365 SharePoint infected files are disallowed for download + (DocsDescription) Ensure Office 365 SharePoint infected files are disallowed for download + .NOTES + CAT + SharePoint Standards + TAG + "CIS" + ADDEDCOMPONENT + IMPACT + Low Impact + ADDEDDATE + 2024-07-09 + POWERSHELLEQUIVALENT + Set-SPOTenant -DisallowInfectedFileDownload \$true + RECOMMENDEDBY + "CIS" + "CIPP" + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/sharepoint-standards#low-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SPDisallowInfectedFiles' + + $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | + Select-Object -Property DisallowInfectedFileDownload + + $StateIsCorrect = ($CurrentState.DisallowInfectedFileDownload -eq $true) + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $tenant -Message 'Downloading Sharepoint infected files are already disallowed.' -Sev Info + } else { + $Properties = @{ + DisallowInfectedFileDownload = $true + } + + try { + Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties + Write-LogMessage -API 'Standards' -tenant $tenant -Message 'Successfully disallowed downloading SharePoint infected files.' -Sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $tenant -Message "Failed to disallow downloading Sharepoint infected files. Error: $ErrorMessage" -Sev Error + } + } + } + + if ($Settings.alert -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $tenant -Message 'Downloading Sharepoint infected files are disallowed.' -Sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -Message 'Downloading Sharepoint infected files are allowed.' -Sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'SPDisallowInfectedFiles' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPEmailAttestation.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPEmailAttestation.ps1 index 0170bd7286cc..a3b808415c65 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPEmailAttestation.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPEmailAttestation.ps1 @@ -1,71 +1,73 @@ -function Invoke-CIPPStandardSPEmailAttestation { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) SPEmailAttestation - .SYNOPSIS - (Label) Require re-authentication with verification code - .DESCRIPTION - (Helptext) Ensure re-authentication with verification code is restricted - (DocsDescription) Ensure re-authentication with verification code is restricted - .NOTES - CAT - SharePoint Standards - TAG - "CIS" - ADDEDCOMPONENT - {"type":"number","name":"standards.SPEmailAttestation.Days","label":"Require re-authentication every X Days (Default 15)"} - IMPACT - Medium Impact - POWERSHELLEQUIVALENT - Set-SPOTenant -EmailAttestationRequired \$true -EmailAttestationReAuthDays 15 - RECOMMENDEDBY - "CIS 3.0" - "CIPP" - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/sharepoint-standards#medium-impact - #> - - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SPEmailAttestation' - - $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | - Select-Object -Property EmailAttestationReAuthDays, EmailAttestationRequired - - $StateIsCorrect = ($CurrentState.EmailAttestationReAuthDays -eq $Settings.Days) -and - ($CurrentState.EmailAttestationRequired -eq $true) - - if ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Sharepoint reauthentication with verification code is already restricted.' -Sev Info - } else { - $Properties = @{ - EmailAttestationReAuthDays = $Settings.Days - EmailAttestationRequired = $true - } - - try { - Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully set reauthentication with verification code restriction.' -Sev Info - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to set reauthentication with verification code restriction. Error: $ErrorMessage" -Sev Error - } - } - } - - if ($Settings.alert -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Reauthentication with verification code is restricted.' -Sev Info - } else { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Reauthentication with verification code is not restricted.' -Sev Alert - } - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'SPEmailAttestation' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant - } -} +function Invoke-CIPPStandardSPEmailAttestation { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) SPEmailAttestation + .SYNOPSIS + (Label) Require re-authentication with verification code + .DESCRIPTION + (Helptext) Ensure re-authentication with verification code is restricted + (DocsDescription) Ensure re-authentication with verification code is restricted + .NOTES + CAT + SharePoint Standards + TAG + "CIS" + ADDEDCOMPONENT + {"type":"number","name":"standards.SPEmailAttestation.Days","label":"Require re-authentication every X Days (Default 15)"} + IMPACT + Medium Impact + ADDEDDATE + 2024-07-09 + POWERSHELLEQUIVALENT + Set-SPOTenant -EmailAttestationRequired \$true -EmailAttestationReAuthDays 15 + RECOMMENDEDBY + "CIS" + "CIPP" + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/sharepoint-standards#medium-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SPEmailAttestation' + + $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | + Select-Object -Property EmailAttestationReAuthDays, EmailAttestationRequired + + $StateIsCorrect = ($CurrentState.EmailAttestationReAuthDays -eq $Settings.Days) -and + ($CurrentState.EmailAttestationRequired -eq $true) + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Sharepoint reauthentication with verification code is already restricted.' -Sev Info + } else { + $Properties = @{ + EmailAttestationReAuthDays = $Settings.Days + EmailAttestationRequired = $true + } + + try { + Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully set reauthentication with verification code restriction.' -Sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to set reauthentication with verification code restriction. Error: $ErrorMessage" -Sev Error + } + } + } + + if ($Settings.alert -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Reauthentication with verification code is restricted.' -Sev Info + } else { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Reauthentication with verification code is not restricted.' -Sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'SPEmailAttestation' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 index 28276672d6c3..b2f7db4c3f68 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 @@ -1,70 +1,72 @@ -function Invoke-CIPPStandardSPExternalUserExpiration { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) SPExternalUserExpiration - .SYNOPSIS - (Label) Set guest access to expire automatically - .DESCRIPTION - (Helptext) Ensure guest access to a site or OneDrive will expire automatically - (DocsDescription) Ensure guest access to a site or OneDrive will expire automatically - .NOTES - CAT - SharePoint Standards - TAG - "CIS" - ADDEDCOMPONENT - {"type":"number","name":"standards.SPExternalUserExpiration.Days","label":"Days until expiration (Default 60)"} - IMPACT - Medium Impact - POWERSHELLEQUIVALENT - Set-SPOTenant -ExternalUserExpireInDays 30 -ExternalUserExpirationRequired \$True - RECOMMENDEDBY - "CIS 3.0" - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/sharepoint-standards#medium-impact - #> - - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SPExternalUserExpiration' - - $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | - Select-Object -Property ExternalUserExpireInDays, ExternalUserExpirationRequired - - $StateIsCorrect = ($CurrentState.ExternalUserExpireInDays -eq $Settings.Days) -and - ($CurrentState.ExternalUserExpirationRequired -eq $true) - - if ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint External User Expiration is already enabled.' -Sev Info - } else { - $Properties = @{ - ExternalUserExpireInDays = $Settings.Days - ExternalUserExpirationRequired = $true - } - - try { - Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully set External User Expiration' -Sev Info - } catch { - $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to set External User Expiration. Error: $($ErrorMessage.NormalizedError)" -Sev Error -LogData $ErrorMessage - } - } - } - - if ($Settings.alert -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'External User Expiration is enabled' -Sev Info - } else { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'External User Expiration is not enabled' -Sev Alert - } - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'ExternalUserExpiration' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant - } -} +function Invoke-CIPPStandardSPExternalUserExpiration { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) SPExternalUserExpiration + .SYNOPSIS + (Label) Set guest access to expire automatically + .DESCRIPTION + (Helptext) Ensure guest access to a site or OneDrive will expire automatically + (DocsDescription) Ensure guest access to a site or OneDrive will expire automatically + .NOTES + CAT + SharePoint Standards + TAG + "CIS" + ADDEDCOMPONENT + {"type":"number","name":"standards.SPExternalUserExpiration.Days","label":"Days until expiration (Default 60)"} + IMPACT + Medium Impact + ADDEDDATE + 2024-07-09 + POWERSHELLEQUIVALENT + Set-SPOTenant -ExternalUserExpireInDays 30 -ExternalUserExpirationRequired \$True + RECOMMENDEDBY + "CIS 3.0" + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/sharepoint-standards#medium-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SPExternalUserExpiration' + + $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | + Select-Object -Property ExternalUserExpireInDays, ExternalUserExpirationRequired + + $StateIsCorrect = ($CurrentState.ExternalUserExpireInDays -eq $Settings.Days) -and + ($CurrentState.ExternalUserExpirationRequired -eq $true) + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint External User Expiration is already enabled.' -Sev Info + } else { + $Properties = @{ + ExternalUserExpireInDays = $Settings.Days + ExternalUserExpirationRequired = $true + } + + try { + Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully set External User Expiration' -Sev Info + } catch { + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to set External User Expiration. Error: $($ErrorMessage.NormalizedError)" -Sev Error -LogData $ErrorMessage + } + } + } + + if ($Settings.alert -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'External User Expiration is enabled' -Sev Info + } else { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'External User Expiration is not enabled' -Sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'ExternalUserExpiration' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPSyncButtonState.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPSyncButtonState.ps1 index 03b66cfe0c3e..bd4b5a81e7b2 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPSyncButtonState.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPSyncButtonState.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardSPSyncButtonState { {"type":"autoComplete","multiple":false,"creatable":false,"label":"SharePoint Sync Button state","name":"standards.SPSyncButtonState.state","options":[{"label":"Disabled","value":"true"},{"label":"Enabled","value":"false"}]} IMPACT Medium Impact + ADDEDDATE + 2024-07-26 POWERSHELLEQUIVALENT Set-SPOTenant -HideSyncButtonOnTeamSite \$true or \$false RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 index 32799e32d5b0..3ad9eb6b025b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 @@ -1,169 +1,171 @@ -function Invoke-CIPPStandardSafeAttachmentPolicy { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) SafeAttachmentPolicy - .SYNOPSIS - (Label) Default Safe Attachment Policy - .DESCRIPTION - (Helptext) This creates a Safe Attachment policy - (DocsDescription) This creates a Safe Attachment policy - .NOTES - CAT - Defender Standards - TAG - "CIS" - "mdo_safedocuments" - "mdo_commonattachmentsfilter" - "mdo_safeattachmentpolicy" - ADDEDCOMPONENT - {"type":"select","multiple":false,"label":"Safe Attachment Action","name":"standards.SafeAttachmentPolicy.SafeAttachmentAction","options":[{"label":"Allow","value":"Allow"},{"label":"Block","value":"Block"},{"label":"DynamicDelivery","value":"DynamicDelivery"}]} - {"type":"select","multiple":false,"label":"QuarantineTag","name":"standards.SafeAttachmentPolicy.QuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} - {"type":"switch","label":"Redirect","name":"standards.SafeAttachmentPolicy.Redirect"} - {"type":"textField","name":"standards.SafeAttachmentPolicy.RedirectAddress","label":"Redirect Address","required":false} - IMPACT - Low Impact - POWERSHELLEQUIVALENT - Set-SafeAttachmentPolicy or New-SafeAttachmentPolicy - RECOMMENDEDBY - "CIS" - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/defender-standards#low-impact - #> - - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SafeAttachmentPolicy' - - $ServicePlans = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/subscribedSkus?$select=servicePlans' -tenantid $Tenant - $ServicePlans = $ServicePlans.servicePlans.servicePlanName - $MDOLicensed = $ServicePlans -contains "ATP_ENTERPRISE" - - if ($MDOLicensed) { - $PolicyList = @('CIPP Default Safe Attachment Policy','Default Safe Attachment Policy') - $ExistingPolicy = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeAttachmentPolicy' | Where-Object -Property Name -In $PolicyList - if ($null -eq $ExistingPolicy.Name) { - $PolicyName = $PolicyList[0] - } else { - $PolicyName = $ExistingPolicy.Name - } - $RuleList = @( 'CIPP Default Safe Attachment Rule','CIPP Default Safe Attachment Policy') - $ExistingRule = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeAttachmentRule' | Where-Object -Property Name -In $RuleList - if ($null -eq $ExistingRule.Name) { - $RuleName = $RuleList[0] - } else { - $RuleName = $ExistingRule.Name - } - - $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeAttachmentPolicy' | - Where-Object -Property Name -EQ $PolicyName | - Select-Object Name, Enable, Action, QuarantineTag, Redirect, RedirectAddress - - $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and - ($CurrentState.Enable -eq $true) -and - ($CurrentState.Action -eq $Settings.SafeAttachmentAction) -and - ($CurrentState.QuarantineTag -eq $Settings.QuarantineTag) -and - ($CurrentState.Redirect -eq $Settings.Redirect) -and - (($null -eq $Settings.RedirectAddress) -or ($CurrentState.RedirectAddress -eq $Settings.RedirectAddress)) - - $AcceptedDomains = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AcceptedDomain' - - $RuleState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeAttachmentRule' | - Where-Object -Property Name -EQ $RuleName | - Select-Object Name, SafeAttachmentPolicy, Priority, RecipientDomainIs - - $RuleStateIsCorrect = ($RuleState.Name -eq $RuleName) -and - ($RuleState.SafeAttachmentPolicy -eq $PolicyName) -and - ($RuleState.Priority -eq 0) -and - (!(Compare-Object -ReferenceObject $RuleState.RecipientDomainIs -DifferenceObject $AcceptedDomains.Name)) - - if ($Settings.remediate -eq $true) { - - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Safe Attachment Policy already correctly configured' -sev Info - } else { - $cmdparams = @{ - Enable = $true - Action = $Settings.SafeAttachmentAction - QuarantineTag = $Settings.QuarantineTag - Redirect = $Settings.Redirect - RedirectAddress = $Settings.RedirectAddress - } - - if ($CurrentState.Name -eq $PolicyName) { - try { - $cmdparams.Add('Identity', $PolicyName) - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-SafeAttachmentPolicy' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Safe Attachment policy $PolicyName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update Safe Attachment policy $PolicyName." -sev Error -LogData $_ - } - } else { - try { - $cmdparams.Add('Name', $PolicyName) - New-ExoRequest -tenantid $Tenant -cmdlet 'New-SafeAttachmentPolicy' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created Safe Attachment policy $PolicyName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Safe Attachment policy $PolicyName." -sev Error -LogData $_ - } - } - } - - if ($RuleStateIsCorrect -eq $false) { - $cmdparams = @{ - Priority = 0 - RecipientDomainIs = $AcceptedDomains.Name - } - - if ($RuleState.SafeAttachmentPolicy -ne $PolicyName) { - $cmdparams.Add('SafeAttachmentPolicy', $PolicyName) - } - - if ($RuleState.Name -eq $RuleName) { - try { - $cmdparams.Add('Identity', $RuleName) - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-SafeAttachmentRule' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Safe Attachment rule $RuleName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update Safe Attachment rule $RuleName." -sev Error -LogData $_ - } - } else { - try { - $cmdparams.Add('Name', $RuleName) - New-ExoRequest -tenantid $Tenant -cmdlet 'New-SafeAttachmentRule' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created Safe Attachment rule $RuleName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Safe Attachment rule $RuleName." -sev Error -LogData $_ - } - } - } - } - - if ($Settings.alert -eq $true) { - - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Safe Attachment Policy is enabled' -sev Info - } else { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Safe Attachment Policy is not enabled' -sev Alert - } - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'SafeAttachmentPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant - } - } else { - if ($Settings.remediate -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Safe Attachment policy: Tenant does not have Microsoft Defender for Office 365 license" -sev Error - } - - if ($Settings.alert -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Safe Attachment Policy is not enabled: Tenant does not have Microsoft Defender for Office 365 license' -sev Alert - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'SafeAttachmentPolicy' -FieldValue $false -StoreAs bool -Tenant $tenant - } - } -} +function Invoke-CIPPStandardSafeAttachmentPolicy { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) SafeAttachmentPolicy + .SYNOPSIS + (Label) Default Safe Attachment Policy + .DESCRIPTION + (Helptext) This creates a Safe Attachment policy + (DocsDescription) This creates a Safe Attachment policy + .NOTES + CAT + Defender Standards + TAG + "CIS" + "mdo_safedocuments" + "mdo_commonattachmentsfilter" + "mdo_safeattachmentpolicy" + ADDEDCOMPONENT + {"type":"select","multiple":false,"label":"Safe Attachment Action","name":"standards.SafeAttachmentPolicy.SafeAttachmentAction","options":[{"label":"Allow","value":"Allow"},{"label":"Block","value":"Block"},{"label":"DynamicDelivery","value":"DynamicDelivery"}]} + {"type":"select","multiple":false,"label":"QuarantineTag","name":"standards.SafeAttachmentPolicy.QuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} + {"type":"switch","label":"Redirect","name":"standards.SafeAttachmentPolicy.Redirect"} + {"type":"textField","name":"standards.SafeAttachmentPolicy.RedirectAddress","label":"Redirect Address","required":false} + IMPACT + Low Impact + ADDEDDATE + 2024-03-25 + POWERSHELLEQUIVALENT + Set-SafeAttachmentPolicy or New-SafeAttachmentPolicy + RECOMMENDEDBY + "CIS" + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/defender-standards#low-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SafeAttachmentPolicy' + + $ServicePlans = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/subscribedSkus?$select=servicePlans' -tenantid $Tenant + $ServicePlans = $ServicePlans.servicePlans.servicePlanName + $MDOLicensed = $ServicePlans -contains "ATP_ENTERPRISE" + + if ($MDOLicensed) { + $PolicyList = @('CIPP Default Safe Attachment Policy','Default Safe Attachment Policy') + $ExistingPolicy = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeAttachmentPolicy' | Where-Object -Property Name -In $PolicyList + if ($null -eq $ExistingPolicy.Name) { + $PolicyName = $PolicyList[0] + } else { + $PolicyName = $ExistingPolicy.Name + } + $RuleList = @( 'CIPP Default Safe Attachment Rule','CIPP Default Safe Attachment Policy') + $ExistingRule = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeAttachmentRule' | Where-Object -Property Name -In $RuleList + if ($null -eq $ExistingRule.Name) { + $RuleName = $RuleList[0] + } else { + $RuleName = $ExistingRule.Name + } + + $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeAttachmentPolicy' | + Where-Object -Property Name -EQ $PolicyName | + Select-Object Name, Enable, Action, QuarantineTag, Redirect, RedirectAddress + + $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and + ($CurrentState.Enable -eq $true) -and + ($CurrentState.Action -eq $Settings.SafeAttachmentAction) -and + ($CurrentState.QuarantineTag -eq $Settings.QuarantineTag) -and + ($CurrentState.Redirect -eq $Settings.Redirect) -and + (($null -eq $Settings.RedirectAddress) -or ($CurrentState.RedirectAddress -eq $Settings.RedirectAddress)) + + $AcceptedDomains = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AcceptedDomain' + + $RuleState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeAttachmentRule' | + Where-Object -Property Name -EQ $RuleName | + Select-Object Name, SafeAttachmentPolicy, Priority, RecipientDomainIs + + $RuleStateIsCorrect = ($RuleState.Name -eq $RuleName) -and + ($RuleState.SafeAttachmentPolicy -eq $PolicyName) -and + ($RuleState.Priority -eq 0) -and + (!(Compare-Object -ReferenceObject $RuleState.RecipientDomainIs -DifferenceObject $AcceptedDomains.Name)) + + if ($Settings.remediate -eq $true) { + + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Safe Attachment Policy already correctly configured' -sev Info + } else { + $cmdparams = @{ + Enable = $true + Action = $Settings.SafeAttachmentAction + QuarantineTag = $Settings.QuarantineTag + Redirect = $Settings.Redirect + RedirectAddress = $Settings.RedirectAddress + } + + if ($CurrentState.Name -eq $PolicyName) { + try { + $cmdparams.Add('Identity', $PolicyName) + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-SafeAttachmentPolicy' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Safe Attachment policy $PolicyName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update Safe Attachment policy $PolicyName." -sev Error -LogData $_ + } + } else { + try { + $cmdparams.Add('Name', $PolicyName) + New-ExoRequest -tenantid $Tenant -cmdlet 'New-SafeAttachmentPolicy' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created Safe Attachment policy $PolicyName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Safe Attachment policy $PolicyName." -sev Error -LogData $_ + } + } + } + + if ($RuleStateIsCorrect -eq $false) { + $cmdparams = @{ + Priority = 0 + RecipientDomainIs = $AcceptedDomains.Name + } + + if ($RuleState.SafeAttachmentPolicy -ne $PolicyName) { + $cmdparams.Add('SafeAttachmentPolicy', $PolicyName) + } + + if ($RuleState.Name -eq $RuleName) { + try { + $cmdparams.Add('Identity', $RuleName) + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-SafeAttachmentRule' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Safe Attachment rule $RuleName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update Safe Attachment rule $RuleName." -sev Error -LogData $_ + } + } else { + try { + $cmdparams.Add('Name', $RuleName) + New-ExoRequest -tenantid $Tenant -cmdlet 'New-SafeAttachmentRule' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created Safe Attachment rule $RuleName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Safe Attachment rule $RuleName." -sev Error -LogData $_ + } + } + } + } + + if ($Settings.alert -eq $true) { + + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Safe Attachment Policy is enabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Safe Attachment Policy is not enabled' -sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'SafeAttachmentPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant + } + } else { + if ($Settings.remediate -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Safe Attachment policy: Tenant does not have Microsoft Defender for Office 365 license" -sev Error + } + + if ($Settings.alert -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Safe Attachment Policy is not enabled: Tenant does not have Microsoft Defender for Office 365 license' -sev Alert + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'SafeAttachmentPolicy' -FieldValue $false -StoreAs bool -Tenant $tenant + } + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 index 830fc109a688..a9ad0f3cbd8d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 @@ -1,177 +1,179 @@ -function Invoke-CIPPStandardSafeLinksPolicy { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) SafeLinksPolicy - .SYNOPSIS - (Label) Default SafeLinks Policy - .DESCRIPTION - (Helptext) This creates a safelink policy that automatically scans, tracks, and and enables safe links for Email, Office, and Teams for both external and internal senders - (DocsDescription) This creates a safelink policy that automatically scans, tracks, and and enables safe links for Email, Office, and Teams for both external and internal senders - .NOTES - CAT - Defender Standards - TAG - "CIS" - "mdo_safelinksforemail" - "mdo_safelinksforOfficeApps" - ADDEDCOMPONENT - {"type":"switch","label":"AllowClickThrough","name":"standards.SafeLinksPolicy.AllowClickThrough"} - {"type":"switch","label":"DisableUrlRewrite","name":"standards.SafeLinksPolicy.DisableUrlRewrite"} - {"type":"switch","label":"EnableOrganizationBranding","name":"standards.SafeLinksPolicy.EnableOrganizationBranding"} - IMPACT - Low Impact - POWERSHELLEQUIVALENT - Set-SafeLinksPolicy or New-SafeLinksPolicy - RECOMMENDEDBY - "CIS" - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/defender-standards#low-impact - #> - - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SafeLinksPolicy' - - $ServicePlans = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/subscribedSkus?$select=servicePlans' -tenantid $Tenant - $ServicePlans = $ServicePlans.servicePlans.servicePlanName - $MDOLicensed = $ServicePlans -contains "ATP_ENTERPRISE" - - if ($MDOLicensed) { - $PolicyList = @('CIPP Default SafeLinks Policy','Default SafeLinks Policy') - $ExistingPolicy = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeLinksPolicy' | Where-Object -Property Name -In $PolicyList - if ($null -eq $ExistingPolicy.Name) { - $PolicyName = $PolicyList[0] - } else { - $PolicyName = $ExistingPolicy.Name - } - $RuleList = @( 'CIPP Default SafeLinks Rule','CIPP Default SafeLinks Policy') - $ExistingRule = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeLinksRule' | Where-Object -Property Name -In $RuleList - if ($null -eq $ExistingRule.Name) { - $RuleName = $RuleList[0] - } else { - $RuleName = $ExistingRule.Name - } - - $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeLinksPolicy' | - Where-Object -Property Name -EQ $PolicyName | - Select-Object Name, EnableSafeLinksForEmail, EnableSafeLinksForTeams, EnableSafeLinksForOffice, TrackClicks, AllowClickThrough, ScanUrls, EnableForInternalSenders, DeliverMessageAfterScan, DisableUrlRewrite, EnableOrganizationBranding - - $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and - ($CurrentState.EnableSafeLinksForEmail -eq $true) -and - ($CurrentState.EnableSafeLinksForTeams -eq $true) -and - ($CurrentState.EnableSafeLinksForOffice -eq $true) -and - ($CurrentState.TrackClicks -eq $true) -and - ($CurrentState.ScanUrls -eq $true) -and - ($CurrentState.EnableForInternalSenders -eq $true) -and - ($CurrentState.DeliverMessageAfterScan -eq $true) -and - ($CurrentState.AllowClickThrough -eq $Settings.AllowClickThrough) -and - ($CurrentState.DisableUrlRewrite -eq $Settings.DisableUrlRewrite) -and - ($CurrentState.EnableOrganizationBranding -eq $Settings.EnableOrganizationBranding) - - $AcceptedDomains = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AcceptedDomain' - - $RuleState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeLinksRule' | - Where-Object -Property Name -EQ $RuleName | - Select-Object Name, SafeLinksPolicy, Priority, RecipientDomainIs - - $RuleStateIsCorrect = ($RuleState.Name -eq $RuleName) -and - ($RuleState.SafeLinksPolicy -eq $PolicyName) -and - ($RuleState.Priority -eq 0) -and - (!(Compare-Object -ReferenceObject $RuleState.RecipientDomainIs -DifferenceObject $AcceptedDomains.Name)) - - if ($Settings.remediate -eq $true) { - - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'SafeLink Policy already correctly configured' -sev Info - } else { - $cmdparams = @{ - EnableSafeLinksForEmail = $true - EnableSafeLinksForTeams = $true - EnableSafeLinksForOffice = $true - TrackClicks = $true - ScanUrls = $true - EnableForInternalSenders = $true - DeliverMessageAfterScan = $true - AllowClickThrough = $Settings.AllowClickThrough - DisableUrlRewrite = $Settings.DisableUrlRewrite - EnableOrganizationBranding = $Settings.EnableOrganizationBranding - } - - if ($CurrentState.Name -eq $Policyname) { - try { - $cmdparams.Add('Identity', $PolicyName) - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-SafeLinksPolicy' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated SafeLink policy $PolicyName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update SafeLink policy $PolicyName." -sev Error -LogData $_ - } - } else { - try { - $cmdparams.Add('Name', $PolicyName) - New-ExoRequest -tenantid $Tenant -cmdlet 'New-SafeLinksPolicy' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created SafeLink policy $PolicyName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create SafeLink policy $PolicyName." -sev Error -LogData $_ - } - } - } - - if ($RuleStateIsCorrect -eq $false) { - $cmdparams = @{ - Priority = 0 - RecipientDomainIs = $AcceptedDomains.Name - } - - if ($RuleState.SafeLinksPolicy -ne $PolicyName) { - $cmdparams.Add('SafeLinksPolicy', $PolicyName) - } - - if ($RuleState.Name -eq $RuleName) { - try { - $cmdparams.Add('Identity', $RuleName) - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-SafeLinksRule' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated SafeLink rule $RuleName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update SafeLink rule $RuleName." -sev Error -LogData $_ - } - } else { - try { - $cmdparams.Add('Name', $RuleName) - New-ExoRequest -tenantid $Tenant -cmdlet 'New-SafeLinksRule' -cmdparams $cmdparams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created SafeLink rule $RuleName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create SafeLink rule $RuleName." -sev Error -LogData $_ - } - } - } - } - - if ($Settings.alert -eq $true) { - - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'SafeLink Policy is enabled' -sev Info - } else { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'SafeLink Policy is not enabled' -sev Alert - } - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'SafeLinksPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant - } - } else { - if ($Settings.remediate -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create SafeLink policy: Tenant does not have Microsoft Defender for Office 365 license" -sev Error - } - - if ($Settings.alert -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'SafeLink Policy is not enabled: Tenant does not have Microsoft Defender for Office 365 license' -sev Alert - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'SafeLinksPolicy' -FieldValue $false -StoreAs bool -Tenant $tenant - } - } -} +function Invoke-CIPPStandardSafeLinksPolicy { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) SafeLinksPolicy + .SYNOPSIS + (Label) Default SafeLinks Policy + .DESCRIPTION + (Helptext) This creates a safelink policy that automatically scans, tracks, and and enables safe links for Email, Office, and Teams for both external and internal senders + (DocsDescription) This creates a safelink policy that automatically scans, tracks, and and enables safe links for Email, Office, and Teams for both external and internal senders + .NOTES + CAT + Defender Standards + TAG + "CIS" + "mdo_safelinksforemail" + "mdo_safelinksforOfficeApps" + ADDEDCOMPONENT + {"type":"switch","label":"AllowClickThrough","name":"standards.SafeLinksPolicy.AllowClickThrough"} + {"type":"switch","label":"DisableUrlRewrite","name":"standards.SafeLinksPolicy.DisableUrlRewrite"} + {"type":"switch","label":"EnableOrganizationBranding","name":"standards.SafeLinksPolicy.EnableOrganizationBranding"} + IMPACT + Low Impact + ADDEDDATE + 2024-03-25 + POWERSHELLEQUIVALENT + Set-SafeLinksPolicy or New-SafeLinksPolicy + RECOMMENDEDBY + "CIS" + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/defender-standards#low-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SafeLinksPolicy' + + $ServicePlans = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/subscribedSkus?$select=servicePlans' -tenantid $Tenant + $ServicePlans = $ServicePlans.servicePlans.servicePlanName + $MDOLicensed = $ServicePlans -contains "ATP_ENTERPRISE" + + if ($MDOLicensed) { + $PolicyList = @('CIPP Default SafeLinks Policy','Default SafeLinks Policy') + $ExistingPolicy = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeLinksPolicy' | Where-Object -Property Name -In $PolicyList + if ($null -eq $ExistingPolicy.Name) { + $PolicyName = $PolicyList[0] + } else { + $PolicyName = $ExistingPolicy.Name + } + $RuleList = @( 'CIPP Default SafeLinks Rule','CIPP Default SafeLinks Policy') + $ExistingRule = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeLinksRule' | Where-Object -Property Name -In $RuleList + if ($null -eq $ExistingRule.Name) { + $RuleName = $RuleList[0] + } else { + $RuleName = $ExistingRule.Name + } + + $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeLinksPolicy' | + Where-Object -Property Name -EQ $PolicyName | + Select-Object Name, EnableSafeLinksForEmail, EnableSafeLinksForTeams, EnableSafeLinksForOffice, TrackClicks, AllowClickThrough, ScanUrls, EnableForInternalSenders, DeliverMessageAfterScan, DisableUrlRewrite, EnableOrganizationBranding + + $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and + ($CurrentState.EnableSafeLinksForEmail -eq $true) -and + ($CurrentState.EnableSafeLinksForTeams -eq $true) -and + ($CurrentState.EnableSafeLinksForOffice -eq $true) -and + ($CurrentState.TrackClicks -eq $true) -and + ($CurrentState.ScanUrls -eq $true) -and + ($CurrentState.EnableForInternalSenders -eq $true) -and + ($CurrentState.DeliverMessageAfterScan -eq $true) -and + ($CurrentState.AllowClickThrough -eq $Settings.AllowClickThrough) -and + ($CurrentState.DisableUrlRewrite -eq $Settings.DisableUrlRewrite) -and + ($CurrentState.EnableOrganizationBranding -eq $Settings.EnableOrganizationBranding) + + $AcceptedDomains = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AcceptedDomain' + + $RuleState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeLinksRule' | + Where-Object -Property Name -EQ $RuleName | + Select-Object Name, SafeLinksPolicy, Priority, RecipientDomainIs + + $RuleStateIsCorrect = ($RuleState.Name -eq $RuleName) -and + ($RuleState.SafeLinksPolicy -eq $PolicyName) -and + ($RuleState.Priority -eq 0) -and + (!(Compare-Object -ReferenceObject $RuleState.RecipientDomainIs -DifferenceObject $AcceptedDomains.Name)) + + if ($Settings.remediate -eq $true) { + + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'SafeLink Policy already correctly configured' -sev Info + } else { + $cmdparams = @{ + EnableSafeLinksForEmail = $true + EnableSafeLinksForTeams = $true + EnableSafeLinksForOffice = $true + TrackClicks = $true + ScanUrls = $true + EnableForInternalSenders = $true + DeliverMessageAfterScan = $true + AllowClickThrough = $Settings.AllowClickThrough + DisableUrlRewrite = $Settings.DisableUrlRewrite + EnableOrganizationBranding = $Settings.EnableOrganizationBranding + } + + if ($CurrentState.Name -eq $Policyname) { + try { + $cmdparams.Add('Identity', $PolicyName) + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-SafeLinksPolicy' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated SafeLink policy $PolicyName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update SafeLink policy $PolicyName." -sev Error -LogData $_ + } + } else { + try { + $cmdparams.Add('Name', $PolicyName) + New-ExoRequest -tenantid $Tenant -cmdlet 'New-SafeLinksPolicy' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created SafeLink policy $PolicyName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create SafeLink policy $PolicyName." -sev Error -LogData $_ + } + } + } + + if ($RuleStateIsCorrect -eq $false) { + $cmdparams = @{ + Priority = 0 + RecipientDomainIs = $AcceptedDomains.Name + } + + if ($RuleState.SafeLinksPolicy -ne $PolicyName) { + $cmdparams.Add('SafeLinksPolicy', $PolicyName) + } + + if ($RuleState.Name -eq $RuleName) { + try { + $cmdparams.Add('Identity', $RuleName) + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-SafeLinksRule' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated SafeLink rule $RuleName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update SafeLink rule $RuleName." -sev Error -LogData $_ + } + } else { + try { + $cmdparams.Add('Name', $RuleName) + New-ExoRequest -tenantid $Tenant -cmdlet 'New-SafeLinksRule' -cmdparams $cmdparams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Created SafeLink rule $RuleName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create SafeLink rule $RuleName." -sev Error -LogData $_ + } + } + } + } + + if ($Settings.alert -eq $true) { + + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'SafeLink Policy is enabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'SafeLink Policy is not enabled' -sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'SafeLinksPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant + } + } else { + if ($Settings.remediate -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create SafeLink policy: Tenant does not have Microsoft Defender for Office 365 license" -sev Error + } + + if ($Settings.alert -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'SafeLink Policy is not enabled: Tenant does not have Microsoft Defender for Office 365 license' -sev Alert + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'SafeLinksPolicy' -FieldValue $false -StoreAs bool -Tenant $tenant + } + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 index cc20e9cd1950..c68ec98e4a0a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 @@ -18,6 +18,8 @@ function Invoke-CIPPStandardSafeSendersDisable { IMPACT Medium Impact + ADDEDDATE + 2023-10-26 POWERSHELLEQUIVALENT Set-MailboxJunkEmailConfiguration RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSecurityDefaults.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSecurityDefaults.ps1 index 1086d7bc1be8..90e2db0be9df 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSecurityDefaults.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSecurityDefaults.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardSecurityDefaults { ADDEDCOMPONENT IMPACT High Impact + ADDEDDATE + 2021-11-19 POWERSHELLEQUIVALENT [Read more here](https://www.cyberdrain.com/automating-with-powershell-enabling-secure-defaults-and-sd-explained/) RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 index df66513ff40c..766b57bf21c0 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardSendFromAlias { ADDEDCOMPONENT IMPACT Medium Impact + ADDEDDATE + 2022-05-25 POWERSHELLEQUIVALENT Set-Mailbox RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 index a3973401f009..90616d76e459 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 @@ -14,10 +14,12 @@ function Invoke-CIPPStandardSendReceiveLimitTenant { Exchange Standards TAG ADDEDCOMPONENT - {"type":"number","name":"standards.SendReceiveLimitTenant.SendLimit","label":"Send limit in MB (Default is 35)","default":35} - {"type":"number","name":"standards.SendReceiveLimitTenant.ReceiveLimit","label":"Receive Limit in MB (Default is 36)","default":36} + {"type":"number","name":"standards.SendReceiveLimitTenant.SendLimit","label":"Send limit in MB (Default is 35)","defaultValue":35} + {"type":"number","name":"standards.SendReceiveLimitTenant.ReceiveLimit","label":"Receive Limit in MB (Default is 36)","defaultValue":36} IMPACT Low Impact + ADDEDDATE + 2023-11-16 POWERSHELLEQUIVALENT Set-MailboxPlan RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 index 6eec8093a260..f1e267db8efd 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 @@ -15,10 +15,12 @@ function Invoke-CIPPStandardShortenMeetings { TAG ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.ShortenMeetings.ShortenEventScopeDefault","options":[{"label":"Disabled/None","value":"None"},{"label":"End early","value":"EndEarly"},{"label":"Start late","value":"StartLate"}]} - {"type":"number","name":"standards.ShortenMeetings.DefaultMinutesToReduceShortEventsBy","label":"Minutes to reduce short calendar events by (Default is 5)","default":5} - {"type":"number","name":"standards.ShortenMeetings.DefaultMinutesToReduceLongEventsBy","label":"Minutes to reduce long calendar events by (Default is 10)","default":10} + {"type":"number","name":"standards.ShortenMeetings.DefaultMinutesToReduceShortEventsBy","label":"Minutes to reduce short calendar events by (Default is 5)","defaultValue":5} + {"type":"number","name":"standards.ShortenMeetings.DefaultMinutesToReduceLongEventsBy","label":"Minutes to reduce long calendar events by (Default is 10)","defaultValue":10} IMPACT Medium Impact + ADDEDDATE + 2024-05-27 POWERSHELLEQUIVALENT Set-OrganizationConfig -ShortenEventScopeDefault -DefaultMinutesToReduceShortEventsBy -DefaultMinutesToReduceLongEventsBy RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 index 953c72248cf9..3c5bc4a59466 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 @@ -1,187 +1,189 @@ -function Invoke-CIPPStandardSpamFilterPolicy { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) SpamFilterPolicy - .SYNOPSIS - (Label) Default Spam Filter Policy - .DESCRIPTION - (Helptext) This standard creates a Spam filter policy similar to the default strict policy. - (DocsDescription) This standard creates a Spam filter policy similar to the default strict policy. - .NOTES - CAT - Defender Standards - TAG - ADDEDCOMPONENT - {"type":"number","label":"Bulk email threshold (Default 7)","name":"standards.SpamFilterPolicy.BulkThreshold","default":7} - {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Spam Action","name":"standards.SpamFilterPolicy.SpamAction","options":[{"label":"Quarantine the message","value":"Quarantine"},{"label":"Move message to Junk Email folder","value":"MoveToJmf"}]} - {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Spam Quarantine Tag","name":"standards.SpamFilterPolicy.SpamQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} - {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"High Confidence Spam Action","name":"standards.SpamFilterPolicy.HighConfidenceSpamAction","options":[{"label":"Quarantine the message","value":"Quarantine"},{"label":"Move message to Junk Email folder","value":"MoveToJmf"}]} - {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"High Confidence Spam Quarantine Tag","name":"standards.SpamFilterPolicy.HighConfidenceSpamQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} - {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Bulk Spam Action","name":"standards.SpamFilterPolicy.BulkSpamAction","options":[{"label":"Quarantine the message","value":"Quarantine"},{"label":"Move message to Junk Email folder","value":"MoveToJmf"}]} - {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Bulk Quarantine Tag","name":"standards.SpamFilterPolicy.BulkQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} - {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Phish Spam Action","name":"standards.SpamFilterPolicy.PhishSpamAction","options":[{"label":"Quarantine the message","value":"Quarantine"},{"label":"Move message to Junk Email folder","value":"MoveToJmf"}]} - {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Phish Quarantine Tag","name":"standards.SpamFilterPolicy.PhishQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} - {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"High Confidence Phish Quarantine Tag","name":"standards.SpamFilterPolicy.HighConfidencePhishQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} - IMPACT - Medium Impact - POWERSHELLEQUIVALENT - New-HostedContentFilterPolicy or Set-HostedContentFilterPolicy - RECOMMENDEDBY - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/defender-standards#medium-impact - #> - - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SpamFilterPolicy' - - $PolicyName = 'CIPP Default Spam Filter Policy' - - $CurrentState = New-ExoRequest -TenantId $Tenant -cmdlet 'Get-HostedContentFilterPolicy' | - Where-Object -Property Name -EQ $PolicyName | - Select-Object -Property * - - $SpamAction = $Settings.SpamAction.value ?? $Settings.SpamAction - $SpamQuarantineTag = $Settings.SpamQuarantineTag.value ?? $Settings.SpamQuarantineTag - $HighConfidenceSpamAction = $Settings.HighConfidenceSpamAction.value ?? $Settings.HighConfidenceSpamAction - $HighConfidenceSpamQuarantineTag = $Settings.HighConfidenceSpamQuarantineTag.value ?? $Settings.HighConfidenceSpamQuarantineTag - $BulkSpamAction = $Settings.BulkSpamAction.value ?? $Settings.BulkSpamAction - $BulkQuarantineTag = $Settings.BulkQuarantineTag.value ?? $Settings.BulkQuarantineTag - $PhishSpamAction = $Settings.PhishSpamAction.value ?? $Settings.PhishSpamAction - $PhishQuarantineTag = $Settings.PhishQuarantineTag.value ?? $Settings.PhishQuarantineTag - $HighConfidencePhishQuarantineTag = $Settings.HighConfidencePhishQuarantineTag.value ?? $Settings.HighConfidencePhishQuarantineTag - - $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and - ($CurrentState.SpamAction -eq $SpamAction) -and - ($CurrentState.SpamQuarantineTag -eq $SpamQuarantineTag) -and - ($CurrentState.HighConfidenceSpamAction -eq $HighConfidenceSpamAction) -and - ($CurrentState.HighConfidenceSpamQuarantineTag -eq $HighConfidenceSpamQuarantineTag) -and - ($CurrentState.BulkSpamAction -eq $BulkSpamAction) -and - ($CurrentState.BulkQuarantineTag -eq $BulkQuarantineTag) -and - ($CurrentState.PhishSpamAction -eq $PhishSpamAction) -and - ($CurrentState.PhishQuarantineTag -eq $PhishQuarantineTag) -and - ($CurrentState.HighConfidencePhishAction -eq 'Quarantine') -and - ($CurrentState.HighConfidencePhishQuarantineTag -eq $HighConfidencePhishQuarantineTag) -and - ($CurrentState.BulkThreshold -eq $Settings.BulkThreshold) -and - ($CurrentState.QuarantineRetentionPeriod -eq 30) -and - ($CurrentState.IncreaseScoreWithNumericIps -eq 'On') -and - ($CurrentState.IncreaseScoreWithRedirectToOtherPort -eq 'On') -and - ($CurrentState.MarkAsSpamEmptyMessages -eq 'On') -and - ($CurrentState.MarkAsSpamJavaScriptInHtml -eq 'On') -and - ($CurrentState.MarkAsSpamSpfRecordHardFail -eq 'On') -and - ($CurrentState.MarkAsSpamFromAddressAuthFail -eq 'On') -and - ($CurrentState.MarkAsSpamNdrBackscatter -eq 'On') -and - ($CurrentState.MarkAsSpamBulkMail -eq 'On') -and - ($CurrentState.InlineSafetyTipsEnabled -eq $true) -and - ($CurrentState.PhishZapEnabled -eq $true) -and - ($CurrentState.SpamZapEnabled -eq $true) - - $AcceptedDomains = New-ExoRequest -TenantId $Tenant -cmdlet 'Get-AcceptedDomain' - - $RuleState = New-ExoRequest -TenantId $Tenant -cmdlet 'Get-HostedContentFilterRule' | - Where-Object -Property Name -EQ $PolicyName | - Select-Object -Property * - - $RuleStateIsCorrect = ($RuleState.Name -eq $PolicyName) -and - ($RuleState.HostedContentFilterPolicy -eq $PolicyName) -and - ($RuleState.Priority -eq 0) -and - (!(Compare-Object -ReferenceObject $RuleState.RecipientDomainIs -DifferenceObject $AcceptedDomains.Name)) - - if ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -message 'Spam Filter Policy already correctly configured' -sev Info - } else { - $cmdparams = @{ - SpamAction = $SpamAction - SpamQuarantineTag = $SpamQuarantineTag - HighConfidenceSpamAction = $HighConfidenceSpamAction - HighConfidenceSpamQuarantineTag = $HighConfidenceSpamQuarantineTag - BulkSpamAction = $BulkSpamAction - BulkQuarantineTag = $BulkQuarantineTag - PhishSpamAction = $PhishSpamAction - PhishQuarantineTag = $PhishQuarantineTag - HighConfidencePhishAction = 'Quarantine' - HighConfidencePhishQuarantineTag = $HighConfidencePhishQuarantineTag - BulkThreshold = $Settings.BulkThreshold - QuarantineRetentionPeriod = 30 - IncreaseScoreWithNumericIps = 'On' - IncreaseScoreWithRedirectToOtherPort = 'On' - MarkAsSpamEmptyMessages = 'On' - MarkAsSpamJavaScriptInHtml = 'On' - MarkAsSpamSpfRecordHardFail = 'On' - MarkAsSpamFromAddressAuthFail = 'On' - MarkAsSpamNdrBackscatter = 'On' - MarkAsSpamBulkMail = 'On' - InlineSafetyTipsEnabled = $true - PhishZapEnabled = $true - SpamZapEnabled = $true - } - Write-Host '================== DEBUG ==================' - Write-Host $cmdParams - - if ($CurrentState.Name -eq $PolicyName) { - try { - $cmdParams.Add('Identity', $PolicyName) - $null = New-ExoRequest -TenantId $Tenant -cmdlet 'Set-HostedContentFilterPolicy' -cmdParams $cmdParams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Updated Spam Filter policy $PolicyName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Failed to update Spam Filter policy $PolicyName." -sev Error -LogData $_ - } - } else { - try { - $cmdParams.Add('Name', $PolicyName) - $null = New-ExoRequest -TenantId $Tenant -cmdlet 'New-HostedContentFilterPolicy' -cmdParams $cmdParams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Created Spam Filter policy $PolicyName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Failed to create Spam Filter policy $PolicyName." -sev Error -LogData $_ - } - } - } - - if ($RuleStateIsCorrect -eq $false) { - $cmdParams = @{ - Priority = 0 - RecipientDomainIs = $AcceptedDomains.Name - } - - if ($RuleState.HostedContentFilterPolicy -ne $PolicyName) { - $cmdParams.Add('HostedContentFilterPolicy', $PolicyName) - } - - if ($RuleState.Name -eq $PolicyName) { - try { - $cmdParams.Add('Identity', "$PolicyName") - $null = New-ExoRequest -TenantId $Tenant -cmdlet 'Set-HostedContentFilterRule' -cmdParams $cmdParams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Updated Spam Filter rule $PolicyName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Failed to update Spam Filter rule $PolicyName." -sev Error -LogData $_ - } - } else { - try { - $cmdParams.Add('Name', "$PolicyName") - $null = New-ExoRequest -TenantId $Tenant -cmdlet 'New-HostedContentFilterRule' -cmdParams $cmdParams -UseSystemMailbox $true - Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Created Spam Filter rule $PolicyName." -sev Info - } catch { - Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Failed to create Spam Filter rule $PolicyName." -sev Error -LogData $_ - } - } - } - } - - if ($Settings.alert -eq $true) { - - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -message 'Spam Filter Policy is enabled' -sev Info - } else { - Write-LogMessage -API 'Standards' -Tenant $Tenant -message 'Spam Filter Policy is not enabled' -sev Alert - } - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'SpamFilterPolicy' -FieldValue $StateIsCorrect -StoreAs [bool] -Tenant $Tenant - } - -} +function Invoke-CIPPStandardSpamFilterPolicy { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) SpamFilterPolicy + .SYNOPSIS + (Label) Default Spam Filter Policy + .DESCRIPTION + (Helptext) This standard creates a Spam filter policy similar to the default strict policy. + (DocsDescription) This standard creates a Spam filter policy similar to the default strict policy. + .NOTES + CAT + Defender Standards + TAG + ADDEDCOMPONENT + {"type":"number","label":"Bulk email threshold (Default 7)","name":"standards.SpamFilterPolicy.BulkThreshold","defaultValue":7} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Spam Action","name":"standards.SpamFilterPolicy.SpamAction","options":[{"label":"Quarantine the message","value":"Quarantine"},{"label":"Move message to Junk Email folder","value":"MoveToJmf"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Spam Quarantine Tag","name":"standards.SpamFilterPolicy.SpamQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"High Confidence Spam Action","name":"standards.SpamFilterPolicy.HighConfidenceSpamAction","options":[{"label":"Quarantine the message","value":"Quarantine"},{"label":"Move message to Junk Email folder","value":"MoveToJmf"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"High Confidence Spam Quarantine Tag","name":"standards.SpamFilterPolicy.HighConfidenceSpamQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Bulk Spam Action","name":"standards.SpamFilterPolicy.BulkSpamAction","options":[{"label":"Quarantine the message","value":"Quarantine"},{"label":"Move message to Junk Email folder","value":"MoveToJmf"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Bulk Quarantine Tag","name":"standards.SpamFilterPolicy.BulkQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Phish Spam Action","name":"standards.SpamFilterPolicy.PhishSpamAction","options":[{"label":"Quarantine the message","value":"Quarantine"},{"label":"Move message to Junk Email folder","value":"MoveToJmf"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"Phish Quarantine Tag","name":"standards.SpamFilterPolicy.PhishQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"label":"High Confidence Phish Quarantine Tag","name":"standards.SpamFilterPolicy.HighConfidencePhishQuarantineTag","options":[{"label":"AdminOnlyAccessPolicy","value":"AdminOnlyAccessPolicy"},{"label":"DefaultFullAccessPolicy","value":"DefaultFullAccessPolicy"},{"label":"DefaultFullAccessWithNotificationPolicy","value":"DefaultFullAccessWithNotificationPolicy"}]} + IMPACT + Medium Impact + ADDEDDATE + 2024-07-15 + POWERSHELLEQUIVALENT + New-HostedContentFilterPolicy or Set-HostedContentFilterPolicy + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/defender-standards#medium-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'SpamFilterPolicy' + + $PolicyName = 'CIPP Default Spam Filter Policy' + + $CurrentState = New-ExoRequest -TenantId $Tenant -cmdlet 'Get-HostedContentFilterPolicy' | + Where-Object -Property Name -EQ $PolicyName | + Select-Object -Property * + + $SpamAction = $Settings.SpamAction.value ?? $Settings.SpamAction + $SpamQuarantineTag = $Settings.SpamQuarantineTag.value ?? $Settings.SpamQuarantineTag + $HighConfidenceSpamAction = $Settings.HighConfidenceSpamAction.value ?? $Settings.HighConfidenceSpamAction + $HighConfidenceSpamQuarantineTag = $Settings.HighConfidenceSpamQuarantineTag.value ?? $Settings.HighConfidenceSpamQuarantineTag + $BulkSpamAction = $Settings.BulkSpamAction.value ?? $Settings.BulkSpamAction + $BulkQuarantineTag = $Settings.BulkQuarantineTag.value ?? $Settings.BulkQuarantineTag + $PhishSpamAction = $Settings.PhishSpamAction.value ?? $Settings.PhishSpamAction + $PhishQuarantineTag = $Settings.PhishQuarantineTag.value ?? $Settings.PhishQuarantineTag + $HighConfidencePhishQuarantineTag = $Settings.HighConfidencePhishQuarantineTag.value ?? $Settings.HighConfidencePhishQuarantineTag + + $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and + ($CurrentState.SpamAction -eq $SpamAction) -and + ($CurrentState.SpamQuarantineTag -eq $SpamQuarantineTag) -and + ($CurrentState.HighConfidenceSpamAction -eq $HighConfidenceSpamAction) -and + ($CurrentState.HighConfidenceSpamQuarantineTag -eq $HighConfidenceSpamQuarantineTag) -and + ($CurrentState.BulkSpamAction -eq $BulkSpamAction) -and + ($CurrentState.BulkQuarantineTag -eq $BulkQuarantineTag) -and + ($CurrentState.PhishSpamAction -eq $PhishSpamAction) -and + ($CurrentState.PhishQuarantineTag -eq $PhishQuarantineTag) -and + ($CurrentState.HighConfidencePhishAction -eq 'Quarantine') -and + ($CurrentState.HighConfidencePhishQuarantineTag -eq $HighConfidencePhishQuarantineTag) -and + ($CurrentState.BulkThreshold -eq $Settings.BulkThreshold) -and + ($CurrentState.QuarantineRetentionPeriod -eq 30) -and + ($CurrentState.IncreaseScoreWithNumericIps -eq 'On') -and + ($CurrentState.IncreaseScoreWithRedirectToOtherPort -eq 'On') -and + ($CurrentState.MarkAsSpamEmptyMessages -eq 'On') -and + ($CurrentState.MarkAsSpamJavaScriptInHtml -eq 'On') -and + ($CurrentState.MarkAsSpamSpfRecordHardFail -eq 'On') -and + ($CurrentState.MarkAsSpamFromAddressAuthFail -eq 'On') -and + ($CurrentState.MarkAsSpamNdrBackscatter -eq 'On') -and + ($CurrentState.MarkAsSpamBulkMail -eq 'On') -and + ($CurrentState.InlineSafetyTipsEnabled -eq $true) -and + ($CurrentState.PhishZapEnabled -eq $true) -and + ($CurrentState.SpamZapEnabled -eq $true) + + $AcceptedDomains = New-ExoRequest -TenantId $Tenant -cmdlet 'Get-AcceptedDomain' + + $RuleState = New-ExoRequest -TenantId $Tenant -cmdlet 'Get-HostedContentFilterRule' | + Where-Object -Property Name -EQ $PolicyName | + Select-Object -Property * + + $RuleStateIsCorrect = ($RuleState.Name -eq $PolicyName) -and + ($RuleState.HostedContentFilterPolicy -eq $PolicyName) -and + ($RuleState.Priority -eq 0) -and + (!(Compare-Object -ReferenceObject $RuleState.RecipientDomainIs -DifferenceObject $AcceptedDomains.Name)) + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -message 'Spam Filter Policy already correctly configured' -sev Info + } else { + $cmdparams = @{ + SpamAction = $SpamAction + SpamQuarantineTag = $SpamQuarantineTag + HighConfidenceSpamAction = $HighConfidenceSpamAction + HighConfidenceSpamQuarantineTag = $HighConfidenceSpamQuarantineTag + BulkSpamAction = $BulkSpamAction + BulkQuarantineTag = $BulkQuarantineTag + PhishSpamAction = $PhishSpamAction + PhishQuarantineTag = $PhishQuarantineTag + HighConfidencePhishAction = 'Quarantine' + HighConfidencePhishQuarantineTag = $HighConfidencePhishQuarantineTag + BulkThreshold = $Settings.BulkThreshold + QuarantineRetentionPeriod = 30 + IncreaseScoreWithNumericIps = 'On' + IncreaseScoreWithRedirectToOtherPort = 'On' + MarkAsSpamEmptyMessages = 'On' + MarkAsSpamJavaScriptInHtml = 'On' + MarkAsSpamSpfRecordHardFail = 'On' + MarkAsSpamFromAddressAuthFail = 'On' + MarkAsSpamNdrBackscatter = 'On' + MarkAsSpamBulkMail = 'On' + InlineSafetyTipsEnabled = $true + PhishZapEnabled = $true + SpamZapEnabled = $true + } + Write-Host '================== DEBUG ==================' + Write-Host $cmdParams + + if ($CurrentState.Name -eq $PolicyName) { + try { + $cmdParams.Add('Identity', $PolicyName) + $null = New-ExoRequest -TenantId $Tenant -cmdlet 'Set-HostedContentFilterPolicy' -cmdParams $cmdParams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Updated Spam Filter policy $PolicyName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Failed to update Spam Filter policy $PolicyName." -sev Error -LogData $_ + } + } else { + try { + $cmdParams.Add('Name', $PolicyName) + $null = New-ExoRequest -TenantId $Tenant -cmdlet 'New-HostedContentFilterPolicy' -cmdParams $cmdParams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Created Spam Filter policy $PolicyName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Failed to create Spam Filter policy $PolicyName." -sev Error -LogData $_ + } + } + } + + if ($RuleStateIsCorrect -eq $false) { + $cmdParams = @{ + Priority = 0 + RecipientDomainIs = $AcceptedDomains.Name + } + + if ($RuleState.HostedContentFilterPolicy -ne $PolicyName) { + $cmdParams.Add('HostedContentFilterPolicy', $PolicyName) + } + + if ($RuleState.Name -eq $PolicyName) { + try { + $cmdParams.Add('Identity', "$PolicyName") + $null = New-ExoRequest -TenantId $Tenant -cmdlet 'Set-HostedContentFilterRule' -cmdParams $cmdParams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Updated Spam Filter rule $PolicyName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Failed to update Spam Filter rule $PolicyName." -sev Error -LogData $_ + } + } else { + try { + $cmdParams.Add('Name', "$PolicyName") + $null = New-ExoRequest -TenantId $Tenant -cmdlet 'New-HostedContentFilterRule' -cmdParams $cmdParams -UseSystemMailbox $true + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Created Spam Filter rule $PolicyName." -sev Info + } catch { + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Failed to create Spam Filter rule $PolicyName." -sev Error -LogData $_ + } + } + } + } + + if ($Settings.alert -eq $true) { + + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -message 'Spam Filter Policy is enabled' -sev Info + } else { + Write-LogMessage -API 'Standards' -Tenant $Tenant -message 'Spam Filter Policy is not enabled' -sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'SpamFilterPolicy' -FieldValue $StateIsCorrect -StoreAs [bool] -Tenant $Tenant + } + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 index e6958b9e686e..9fadf659d79a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 @@ -18,6 +18,8 @@ function Invoke-CIPPStandardSpoofWarn { {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.SpoofWarn.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} IMPACT Low Impact + ADDEDDATE + 2021-11-16 POWERSHELLEQUIVALENT Set-ExternalInOutlook –Enabled \$true or \$false RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 index 31b1afda1e09..f380385c7424 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 @@ -20,6 +20,8 @@ function Invoke-CIPPStandardStaleEntraDevices { IMPACT High Impact + ADDEDDATE + 2025-01-19 POWERSHELLEQUIVALENT Remove-MgDevice, Update-MgDevice or Graph API RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTAP.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTAP.ps1 index 7800b55045bb..8bcb90248721 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTAP.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTAP.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardTAP { {"type":"autoComplete","multiple":false,"creatable":false,"label":"Select TAP Lifetime","name":"standards.TAP.config","options":[{"label":"Only Once","value":"true"},{"label":"Multiple Logons","value":"false"}]} IMPACT Low Impact + ADDEDDATE + 2022-03-15 POWERSHELLEQUIVALENT Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEmailIntegration.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEmailIntegration.ps1 index 5aec26f2c951..5c56f3973b0e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEmailIntegration.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEmailIntegration.ps1 @@ -1,70 +1,72 @@ -Function Invoke-CIPPStandardTeamsEmailIntegration { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) TeamsEmailIntegration - .SYNOPSIS - (Label) Disallow emails to be sent to channel email addresses - .DESCRIPTION - (Helptext) Should users be allowed to send emails directly to a channel email addresses? - (DocsDescription) Teams channel email addresses are an optional feature that allows users to email the Teams channel directly. - .NOTES - CAT - Teams Standards - TAG - ADDEDCOMPONENT - {"type":"switch","name":"standards.TeamsEmailIntegration.AllowEmailIntoChannel","label":"Allow channel emails"} - IMPACT - Low Impact - POWERSHELLEQUIVALENT - Set-CsTeamsClientConfiguration -AllowEmailIntoChannel \$false - RECOMMENDEDBY - "CIS 3.0" - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/teams-standards#low-impact - #> - - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsEmailIntegration' - - $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsClientConfiguration' -CmdParams @{Identity = 'Global' } - | Select-Object AllowEmailIntoChannel - - if ($null -eq $Settings.AllowEmailIntoChannel) { $Settings.AllowEmailIntoChannel = $false } - - $StateIsCorrect = ($CurrentState.AllowEmailIntoChannel -eq $Settings.AllowEmailIntoChannel) - - if ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams Email Integration settings already set.' -sev Info - } else { - $cmdparams = @{ - Identity = 'Global' - AllowEmailIntoChannel = $Settings.AllowEmailIntoChannel - } - - try { - New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTeamsClientConfiguration' -CmdParams $cmdparams - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated Teams Email Integration settings' -sev Info - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Teams Email Integration settings. Error: $ErrorMessage" -sev Error - } - } - } - - if ($Settings.alert -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams Email Integration settings is set correctly.' -sev Info - } else { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams Email Integration settings is not set correctly.' -sev Alert - } - } - - if ($Setings.report -eq $true) { - Add-CIPPBPAField -FieldName 'TeamsEmailIntoChannel' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant - } -} +Function Invoke-CIPPStandardTeamsEmailIntegration { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) TeamsEmailIntegration + .SYNOPSIS + (Label) Disallow emails to be sent to channel email addresses + .DESCRIPTION + (Helptext) Should users be allowed to send emails directly to a channel email addresses? + (DocsDescription) Teams channel email addresses are an optional feature that allows users to email the Teams channel directly. + .NOTES + CAT + Teams Standards + TAG + ADDEDCOMPONENT + {"type":"switch","name":"standards.TeamsEmailIntegration.AllowEmailIntoChannel","label":"Allow channel emails"} + IMPACT + Low Impact + ADDEDDATE + 2024-07-30 + POWERSHELLEQUIVALENT + Set-CsTeamsClientConfiguration -AllowEmailIntoChannel \$false + RECOMMENDEDBY + "CIS 3.0" + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/teams-standards#low-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsEmailIntegration' + + $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsClientConfiguration' -CmdParams @{Identity = 'Global' } + | Select-Object AllowEmailIntoChannel + + if ($null -eq $Settings.AllowEmailIntoChannel) { $Settings.AllowEmailIntoChannel = $false } + + $StateIsCorrect = ($CurrentState.AllowEmailIntoChannel -eq $Settings.AllowEmailIntoChannel) + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams Email Integration settings already set.' -sev Info + } else { + $cmdparams = @{ + Identity = 'Global' + AllowEmailIntoChannel = $Settings.AllowEmailIntoChannel + } + + try { + New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTeamsClientConfiguration' -CmdParams $cmdparams + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated Teams Email Integration settings' -sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Teams Email Integration settings. Error: $ErrorMessage" -sev Error + } + } + } + + if ($Settings.alert -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams Email Integration settings is set correctly.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams Email Integration settings is not set correctly.' -sev Alert + } + } + + if ($Setings.report -eq $true) { + Add-CIPPBPAField -FieldName 'TeamsEmailIntoChannel' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEnrollUser.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEnrollUser.ps1 index 77d3aa8258b6..2bf0c363a414 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEnrollUser.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEnrollUser.ps1 @@ -1,69 +1,71 @@ -Function Invoke-CIPPStandardTeamsEnrollUser { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) TeamsEnrollUser - .SYNOPSIS - (Label) Default voice and face enrollment - .DESCRIPTION - (Helptext) Controls whether users with this policy can set the voice profile capture and enrollment through the Recognition tab in their Teams client settings. - (DocsDescription) Controls whether users with this policy can set the voice profile capture and enrollment through the Recognition tab in their Teams client settings. - .NOTES - CAT - Teams Standards - TAG - ADDEDCOMPONENT - {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.TeamsEnrollUser.EnrollUserOverride","label":"Voice and Face Enrollment","options":[{"label":"Disabled","value":"Disabled"},{"label":"Enabled","value":"Enabled"}]} - IMPACT - Low Impact - POWERSHELLEQUIVALENT - Set-CsTeamsMeetingPolicy -Identity Global -EnrollUserOverride \$false - RECOMMENDEDBY - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/teams-standards#low-impact - #> - - param($Tenant, $Settings) - - # Get EnrollUserOverride value using null-coalescing operator - $enrollUserOverride = $Settings.EnrollUserOverride.value ?? $Settings.EnrollUserOverride - - $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsMeetingPolicy' -cmdParams @{Identity = 'Global' } - | Select-Object EnrollUserOverride - - $StateIsCorrect = ($CurrentState.EnrollUserOverride -eq $enrollUserOverride) - - if ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Teams Enroll User Override settings already set to $enrollUserOverride." -sev Info - } else { - $cmdParams = @{ - Identity = 'Global' - EnrollUserOverride = $enrollUserOverride - } - - try { - $null = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTeamsMeetingPolicy' -cmdParams $cmdParams - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Teams Enroll User Override setting to $enrollUserOverride." -sev Info - } catch { - $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Teams Enroll User Override setting to $enrollUserOverride." -sev Error -LogData $ErrorMessage - } - } - } - - if ($Settings.alert -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams Enroll User Override settings is set correctly.' -sev Info - } else { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams Enroll User Override settings is not set correctly.' -sev Alert - } - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'TeamsEnrollUser' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant - } -} +Function Invoke-CIPPStandardTeamsEnrollUser { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) TeamsEnrollUser + .SYNOPSIS + (Label) Default voice and face enrollment + .DESCRIPTION + (Helptext) Controls whether users with this policy can set the voice profile capture and enrollment through the Recognition tab in their Teams client settings. + (DocsDescription) Controls whether users with this policy can set the voice profile capture and enrollment through the Recognition tab in their Teams client settings. + .NOTES + CAT + Teams Standards + TAG + ADDEDCOMPONENT + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.TeamsEnrollUser.EnrollUserOverride","label":"Voice and Face Enrollment","options":[{"label":"Disabled","value":"Disabled"},{"label":"Enabled","value":"Enabled"}]} + IMPACT + Low Impact + ADDEDDATE + 2024-11-12 + POWERSHELLEQUIVALENT + Set-CsTeamsMeetingPolicy -Identity Global -EnrollUserOverride \$false + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/teams-standards#low-impact + #> + + param($Tenant, $Settings) + + # Get EnrollUserOverride value using null-coalescing operator + $enrollUserOverride = $Settings.EnrollUserOverride.value ?? $Settings.EnrollUserOverride + + $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsMeetingPolicy' -cmdParams @{Identity = 'Global' } + | Select-Object EnrollUserOverride + + $StateIsCorrect = ($CurrentState.EnrollUserOverride -eq $enrollUserOverride) + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Teams Enroll User Override settings already set to $enrollUserOverride." -sev Info + } else { + $cmdParams = @{ + Identity = 'Global' + EnrollUserOverride = $enrollUserOverride + } + + try { + $null = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTeamsMeetingPolicy' -cmdParams $cmdParams + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Updated Teams Enroll User Override setting to $enrollUserOverride." -sev Info + } catch { + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Teams Enroll User Override setting to $enrollUserOverride." -sev Error -LogData $ErrorMessage + } + } + } + + if ($Settings.alert -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams Enroll User Override settings is set correctly.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams Enroll User Override settings is not set correctly.' -sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'TeamsEnrollUser' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalAccessPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalAccessPolicy.ps1 index 77215de033b1..5324de381633 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalAccessPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalAccessPolicy.ps1 @@ -1,77 +1,79 @@ -Function Invoke-CIPPStandardTeamsExternalAccessPolicy { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) TeamsExternalAccessPolicy - .SYNOPSIS - (Label) External Access Settings for Microsoft Teams - .DESCRIPTION - (Helptext) Sets the properties of the Global external access policy. - (DocsDescription) Sets the properties of the Global external access policy. External access policies determine whether or not your users can: 1) communicate with users who have Session Initiation Protocol (SIP) accounts with a federated organization; 2) communicate with users who are using custom applications built with Azure Communication Services; 3) access Skype for Business Server over the Internet, without having to log on to your internal network; 4) communicate with users who have SIP accounts with a public instant messaging (IM) provider such as Skype; and, 5) communicate with people who are using Teams with an account that's not managed by an organization. - .NOTES - CAT - Teams Standards - TAG - ADDEDCOMPONENT - {"type":"switch","name":"standards.TeamsExternalAccessPolicy.EnableFederationAccess","label":"Allow communication from trusted organizations"} - {"type":"switch","name":"standards.TeamsExternalAccessPolicy.EnablePublicCloudAccess","label":"Allow user to communicate with Skype users"} - {"type":"switch","name":"standards.TeamsExternalAccessPolicy.EnableTeamsConsumerAccess","label":"Allow communication with unmanaged Teams accounts"} - IMPACT - Medium Impact - POWERSHELLEQUIVALENT - Set-CsExternalAccessPolicy - RECOMMENDEDBY - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/teams-standards#medium-impact - #> - - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsExternalAccessPolicy' - - $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsExternalAccessPolicy' -CmdParams @{Identity = 'Global' } - | Select-Object * - - if ($null -eq $Settings.EnableFederationAccess) { $Settings.EnableFederationAccess = $false } - if ($null -eq $Settings.EnablePublicCloudAccess) { $Settings.EnablePublicCloudAccess = $false } - if ($null -eq $Settings.EnableTeamsConsumerAccess) { $Settings.EnableTeamsConsumerAccess = $false } - - $StateIsCorrect = ($CurrentState.EnableFederationAccess -eq $Settings.EnableFederationAccess) -and - ($CurrentState.EnablePublicCloudAccess -eq $Settings.EnablePublicCloudAccess) -and - ($CurrentState.EnableTeamsConsumerAccess -eq $Settings.EnableTeamsConsumerAccess) - - if ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'External Access Policy already set.' -sev Info - } else { - $cmdparams = @{ - Identity = 'Global' - EnableFederationAccess = $Settings.EnableFederationAccess - EnablePublicCloudAccess = $Settings.EnablePublicCloudAccess - EnableTeamsConsumerAccess = $Settings.EnableTeamsConsumerAccess - } - - try { - New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsExternalAccessPolicy' -CmdParams $cmdparams - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated External Access Policy' -sev Info - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set External Access Policy. Error: $ErrorMessage" -sev Error - } - } - } - - if ($Settings.alert -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'External Access Policy is set correctly.' -sev Info - } else { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'External Access Policy is not set correctly.' -sev Alert - } - } - - if ($Setings.report -eq $true) { - Add-CIPPBPAField -FieldName 'TeamsExternalAccessPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant - } -} +Function Invoke-CIPPStandardTeamsExternalAccessPolicy { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) TeamsExternalAccessPolicy + .SYNOPSIS + (Label) External Access Settings for Microsoft Teams + .DESCRIPTION + (Helptext) Sets the properties of the Global external access policy. + (DocsDescription) Sets the properties of the Global external access policy. External access policies determine whether or not your users can: 1) communicate with users who have Session Initiation Protocol (SIP) accounts with a federated organization; 2) communicate with users who are using custom applications built with Azure Communication Services; 3) access Skype for Business Server over the Internet, without having to log on to your internal network; 4) communicate with users who have SIP accounts with a public instant messaging (IM) provider such as Skype; and, 5) communicate with people who are using Teams with an account that's not managed by an organization. + .NOTES + CAT + Teams Standards + TAG + ADDEDCOMPONENT + {"type":"switch","name":"standards.TeamsExternalAccessPolicy.EnableFederationAccess","label":"Allow communication from trusted organizations"} + {"type":"switch","name":"standards.TeamsExternalAccessPolicy.EnablePublicCloudAccess","label":"Allow user to communicate with Skype users"} + {"type":"switch","name":"standards.TeamsExternalAccessPolicy.EnableTeamsConsumerAccess","label":"Allow communication with unmanaged Teams accounts"} + IMPACT + Medium Impact + ADDEDDATE + 2024-07-30 + POWERSHELLEQUIVALENT + Set-CsExternalAccessPolicy + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/teams-standards#medium-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsExternalAccessPolicy' + + $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsExternalAccessPolicy' -CmdParams @{Identity = 'Global' } + | Select-Object * + + if ($null -eq $Settings.EnableFederationAccess) { $Settings.EnableFederationAccess = $false } + if ($null -eq $Settings.EnablePublicCloudAccess) { $Settings.EnablePublicCloudAccess = $false } + if ($null -eq $Settings.EnableTeamsConsumerAccess) { $Settings.EnableTeamsConsumerAccess = $false } + + $StateIsCorrect = ($CurrentState.EnableFederationAccess -eq $Settings.EnableFederationAccess) -and + ($CurrentState.EnablePublicCloudAccess -eq $Settings.EnablePublicCloudAccess) -and + ($CurrentState.EnableTeamsConsumerAccess -eq $Settings.EnableTeamsConsumerAccess) + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'External Access Policy already set.' -sev Info + } else { + $cmdparams = @{ + Identity = 'Global' + EnableFederationAccess = $Settings.EnableFederationAccess + EnablePublicCloudAccess = $Settings.EnablePublicCloudAccess + EnableTeamsConsumerAccess = $Settings.EnableTeamsConsumerAccess + } + + try { + New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsExternalAccessPolicy' -CmdParams $cmdparams + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated External Access Policy' -sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set External Access Policy. Error: $ErrorMessage" -sev Error + } + } + } + + if ($Settings.alert -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'External Access Policy is set correctly.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'External Access Policy is not set correctly.' -sev Alert + } + } + + if ($Setings.report -eq $true) { + Add-CIPPBPAField -FieldName 'TeamsExternalAccessPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalFileSharing.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalFileSharing.ps1 index dbde0768fccd..356b514e7eb0 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalFileSharing.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalFileSharing.ps1 @@ -1,85 +1,87 @@ -Function Invoke-CIPPStandardTeamsExternalFileSharing { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) TeamsExternalFileSharing - .SYNOPSIS - (Label) Define approved cloud storage services for external file sharing in Teams - .DESCRIPTION - (Helptext) Ensure external file sharing in Teams is enabled for only approved cloud storage services. - (DocsDescription) Ensure external file sharing in Teams is enabled for only approved cloud storage services. - .NOTES - CAT - Teams Standards - TAG - ADDEDCOMPONENT - {"type":"switch","name":"standards.TeamsExternalFileSharing.AllowGoogleDrive","label":"Allow Google Drive"} - {"type":"switch","name":"standards.TeamsExternalFileSharing.AllowShareFile","label":"Allow ShareFile"} - {"type":"switch","name":"standards.TeamsExternalFileSharing.AllowBox","label":"Allow Box"} - {"type":"switch","name":"standards.TeamsExternalFileSharing.AllowDropBox","label":"Allow Dropbox"} - {"type":"switch","name":"standards.TeamsExternalFileSharing.AllowEgnyte","label":"Allow Egnyte"} - IMPACT - Low Impact - POWERSHELLEQUIVALENT - Set-CsTeamsClientConfiguration -AllowGoogleDrive \$false -AllowShareFile \$false -AllowBox \$false -AllowDropBox \$false -AllowEgnyte \$false - RECOMMENDEDBY - "CIS 3.0" - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/teams-standards#low-impact - #> - - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsExternalFileSharing' - - $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsClientConfiguration' - | Select-Object AllowGoogleDrive, AllowShareFile, AllowBox, AllowDropBox, AllowEgnyte - - if ($null -eq $Settings.AllowGoogleDrive) { $Settings.AllowGoogleDrive = $false } - if ($null -eq $Settings.AllowShareFile) { $Settings.AllowShareFile = $false } - if ($null -eq $Settings.AllowBox) { $Settings.AllowBox = $false } - if ($null -eq $Settings.AllowDropBox) { $Settings.AllowDropBox = $false } - if ($null -eq $Settings.AllowEgnyte) { $Settings.AllowEgnyte = $false } - - $StateIsCorrect = ($CurrentState.AllowGoogleDrive -eq $Settings.AllowGoogleDrive) -and - ($CurrentState.AllowShareFile -eq $Settings.AllowShareFile) -and - ($CurrentState.AllowBox -eq $Settings.AllowBox) -and - ($CurrentState.AllowDropBox -eq $Settings.AllowDropBox) -and - ($CurrentState.AllowEgnyte -eq $Settings.AllowEgnyte) - - if ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams External File Sharing already set.' -sev Info - } else { - $cmdparams = @{ - AllowGoogleDrive = $Settings.AllowGoogleDrive - AllowShareFile = $Settings.AllowShareFile - AllowBox = $Settings.AllowBox - AllowDropBox = $Settings.AllowDropBox - AllowEgnyte = $Settings.AllowEgnyte - } - - try { - New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTeamsClientConfiguration' -CmdParams $cmdparams - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated Teams External File Sharing' -sev Info - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Teams External File Sharing. Error: $ErrorMessage" -sev Error - } - } - } - - if ($Settings.alert -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams External File Sharing is set correctly.' -sev Info - } else { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams External File Sharing is not set correctly.' -sev Alert - } - } - - if ($Setings.report -eq $true) { - Add-CIPPBPAField -FieldName 'TeamsExternalFileSharing' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant - } -} +Function Invoke-CIPPStandardTeamsExternalFileSharing { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) TeamsExternalFileSharing + .SYNOPSIS + (Label) Define approved cloud storage services for external file sharing in Teams + .DESCRIPTION + (Helptext) Ensure external file sharing in Teams is enabled for only approved cloud storage services. + (DocsDescription) Ensure external file sharing in Teams is enabled for only approved cloud storage services. + .NOTES + CAT + Teams Standards + TAG + ADDEDCOMPONENT + {"type":"switch","name":"standards.TeamsExternalFileSharing.AllowGoogleDrive","label":"Allow Google Drive"} + {"type":"switch","name":"standards.TeamsExternalFileSharing.AllowShareFile","label":"Allow ShareFile"} + {"type":"switch","name":"standards.TeamsExternalFileSharing.AllowBox","label":"Allow Box"} + {"type":"switch","name":"standards.TeamsExternalFileSharing.AllowDropBox","label":"Allow Dropbox"} + {"type":"switch","name":"standards.TeamsExternalFileSharing.AllowEgnyte","label":"Allow Egnyte"} + IMPACT + Low Impact + ADDEDDATE + 2024-07-28 + POWERSHELLEQUIVALENT + Set-CsTeamsClientConfiguration -AllowGoogleDrive \$false -AllowShareFile \$false -AllowBox \$false -AllowDropBox \$false -AllowEgnyte \$false + RECOMMENDEDBY + "CIS 3.0" + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/teams-standards#low-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsExternalFileSharing' + + $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsClientConfiguration' + | Select-Object AllowGoogleDrive, AllowShareFile, AllowBox, AllowDropBox, AllowEgnyte + + if ($null -eq $Settings.AllowGoogleDrive) { $Settings.AllowGoogleDrive = $false } + if ($null -eq $Settings.AllowShareFile) { $Settings.AllowShareFile = $false } + if ($null -eq $Settings.AllowBox) { $Settings.AllowBox = $false } + if ($null -eq $Settings.AllowDropBox) { $Settings.AllowDropBox = $false } + if ($null -eq $Settings.AllowEgnyte) { $Settings.AllowEgnyte = $false } + + $StateIsCorrect = ($CurrentState.AllowGoogleDrive -eq $Settings.AllowGoogleDrive) -and + ($CurrentState.AllowShareFile -eq $Settings.AllowShareFile) -and + ($CurrentState.AllowBox -eq $Settings.AllowBox) -and + ($CurrentState.AllowDropBox -eq $Settings.AllowDropBox) -and + ($CurrentState.AllowEgnyte -eq $Settings.AllowEgnyte) + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams External File Sharing already set.' -sev Info + } else { + $cmdparams = @{ + AllowGoogleDrive = $Settings.AllowGoogleDrive + AllowShareFile = $Settings.AllowShareFile + AllowBox = $Settings.AllowBox + AllowDropBox = $Settings.AllowDropBox + AllowEgnyte = $Settings.AllowEgnyte + } + + try { + New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTeamsClientConfiguration' -CmdParams $cmdparams + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated Teams External File Sharing' -sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Teams External File Sharing. Error: $ErrorMessage" -sev Error + } + } + } + + if ($Settings.alert -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams External File Sharing is set correctly.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams External File Sharing is not set correctly.' -sev Alert + } + } + + if ($Setings.report -eq $true) { + Add-CIPPBPAField -FieldName 'TeamsExternalFileSharing' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 index 0f191dd0149d..a17b92451ff6 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 @@ -1,117 +1,119 @@ -Function Invoke-CIPPStandardTeamsFederationConfiguration { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) TeamsFederationConfiguration - .SYNOPSIS - (Label) Federation Configuration for Microsoft Teams - .DESCRIPTION - (Helptext) Sets the properties of the Global federation configuration. - (DocsDescription) Sets the properties of the Global federation configuration. Federation configuration settings determine whether or not your users can communicate with users who have SIP accounts with a federated organization. - .NOTES - CAT - Teams Standards - TAG - ADDEDCOMPONENT - {"type":"switch","name":"standards.TeamsFederationConfiguration.AllowTeamsConsumer","label":"Allow users to communicate with other organizations"} - {"type":"switch","name":"standards.TeamsFederationConfiguration.AllowPublicUsers","label":"Allow users to communicate with Skype Users"} - {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.TeamsFederationConfiguration.DomainControl","label":"Communication Mode","options":[{"label":"Allow all external domains","value":"AllowAllExternal"},{"label":"Block all external domains","value":"BlockAllExternal"},{"label":"Allow specific external domains","value":"AllowSpecificExternal"},{"label":"Block specific external domains","value":"BlockSpecificExternal"}]} - {"type":"textField","name":"standards.TeamsFederationConfiguration.DomainList","label":"Domains, Comma separated","required":false} - IMPACT - Medium Impact - POWERSHELLEQUIVALENT - Set-CsTenantFederationConfiguration - RECOMMENDEDBY - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/teams-standards#medium-impact - #> - - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsFederationConfiguration' - - $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTenantFederationConfiguration' -CmdParams @{Identity = 'Global' } - | Select-Object * - - $DomainControl = $Settings.DomainControl.value ?? $Settings.DomainControl - Switch ($DomainControl) { - 'AllowAllExternal' { - $AllowFederatedUsers = $true - $AllowedDomainsAsAList = 'AllowAllKnownDomains' - $BlockedDomains = @() - } - 'BlockAllExternal' { - $AllowFederatedUsers = $false - $AllowedDomainsAsAList = 'AllowAllKnownDomains' - $BlockedDomains = @() - } - 'AllowSpecificExternal' { - $AllowFederatedUsers = $true - $BlockedDomains = @() - if ($null -ne $Settings.DomainList) { - $AllowedDomainsAsAList = @($Settings.DomainList).Split(',').Trim() - } else { - $AllowedDomainsAsAList = @() - } - } - 'BlockSpecificExternal' { - $AllowFederatedUsers = $true - $AllowedDomainsAsAList = 'AllowAllKnownDomains' - if ($null -ne $Settings.DomainList) { - $BlockedDomains = @($Settings.DomainList).Split(',').Trim() - } else { - $BlockedDomains = @() - } - } - Default { - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Federation Configuration: Invalid $DomainControl parameter" -sev Error - Return - } - } - - # TODO : Add proper validation for the domain list - # $CurrentState.AllowedDomains returns a PSObject System.Object and adds a Domain= for each allowed domain, ex {Domain=example.com, Domain=example2.com} - - $StateIsCorrect = ($CurrentState.AllowTeamsConsumer -eq $Settings.AllowTeamsConsumer) -and - ($CurrentState.AllowPublicUsers -eq $Settings.AllowPublicUsers) -and - ($CurrentState.AllowFederatedUsers -eq $AllowFederatedUsers) -and - ($CurrentState.AllowedDomains -eq $AllowedDomainsAsAList) -and - ($CurrentState.BlockedDomains -eq $BlockedDomains) - - if ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Federation Configuration already set.' -sev Info - } else { - $cmdparams = @{ - Identity = 'Global' - AllowTeamsConsumer = $Settings.AllowTeamsConsumer - AllowPublicUsers = $Settings.AllowPublicUsers - AllowFederatedUsers = $AllowFederatedUsers - AllowedDomainsAsAList = $AllowedDomainsAsAList - BlockedDomains = $BlockedDomains - } - - try { - New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTenantFederationConfiguration' -CmdParams $cmdparams - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated Federation Configuration Policy' -sev Info - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Federation Configuration Policy. Error: $ErrorMessage" -sev Error - } - } - } - - if ($Settings.alert -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Federation Configuration is set correctly.' -sev Info - } else { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Federation Configuration is not set correctly.' -sev Alert - } - } - - if ($Setings.report -eq $true) { - Add-CIPPBPAField -FieldName 'FederationConfiguration' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant - } -} +Function Invoke-CIPPStandardTeamsFederationConfiguration { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) TeamsFederationConfiguration + .SYNOPSIS + (Label) Federation Configuration for Microsoft Teams + .DESCRIPTION + (Helptext) Sets the properties of the Global federation configuration. + (DocsDescription) Sets the properties of the Global federation configuration. Federation configuration settings determine whether or not your users can communicate with users who have SIP accounts with a federated organization. + .NOTES + CAT + Teams Standards + TAG + ADDEDCOMPONENT + {"type":"switch","name":"standards.TeamsFederationConfiguration.AllowTeamsConsumer","label":"Allow users to communicate with other organizations"} + {"type":"switch","name":"standards.TeamsFederationConfiguration.AllowPublicUsers","label":"Allow users to communicate with Skype Users"} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.TeamsFederationConfiguration.DomainControl","label":"Communication Mode","options":[{"label":"Allow all external domains","value":"AllowAllExternal"},{"label":"Block all external domains","value":"BlockAllExternal"},{"label":"Allow specific external domains","value":"AllowSpecificExternal"},{"label":"Block specific external domains","value":"BlockSpecificExternal"}]} + {"type":"textField","name":"standards.TeamsFederationConfiguration.DomainList","label":"Domains, Comma separated","required":false} + IMPACT + Medium Impact + ADDEDDATE + 2024-07-31 + POWERSHELLEQUIVALENT + Set-CsTenantFederationConfiguration + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/teams-standards#medium-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsFederationConfiguration' + + $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTenantFederationConfiguration' -CmdParams @{Identity = 'Global' } + | Select-Object * + + $DomainControl = $Settings.DomainControl.value ?? $Settings.DomainControl + Switch ($DomainControl) { + 'AllowAllExternal' { + $AllowFederatedUsers = $true + $AllowedDomainsAsAList = 'AllowAllKnownDomains' + $BlockedDomains = @() + } + 'BlockAllExternal' { + $AllowFederatedUsers = $false + $AllowedDomainsAsAList = 'AllowAllKnownDomains' + $BlockedDomains = @() + } + 'AllowSpecificExternal' { + $AllowFederatedUsers = $true + $BlockedDomains = @() + if ($null -ne $Settings.DomainList) { + $AllowedDomainsAsAList = @($Settings.DomainList).Split(',').Trim() + } else { + $AllowedDomainsAsAList = @() + } + } + 'BlockSpecificExternal' { + $AllowFederatedUsers = $true + $AllowedDomainsAsAList = 'AllowAllKnownDomains' + if ($null -ne $Settings.DomainList) { + $BlockedDomains = @($Settings.DomainList).Split(',').Trim() + } else { + $BlockedDomains = @() + } + } + Default { + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Federation Configuration: Invalid $DomainControl parameter" -sev Error + Return + } + } + + # TODO : Add proper validation for the domain list + # $CurrentState.AllowedDomains returns a PSObject System.Object and adds a Domain= for each allowed domain, ex {Domain=example.com, Domain=example2.com} + + $StateIsCorrect = ($CurrentState.AllowTeamsConsumer -eq $Settings.AllowTeamsConsumer) -and + ($CurrentState.AllowPublicUsers -eq $Settings.AllowPublicUsers) -and + ($CurrentState.AllowFederatedUsers -eq $AllowFederatedUsers) -and + ($CurrentState.AllowedDomains -eq $AllowedDomainsAsAList) -and + ($CurrentState.BlockedDomains -eq $BlockedDomains) + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Federation Configuration already set.' -sev Info + } else { + $cmdparams = @{ + Identity = 'Global' + AllowTeamsConsumer = $Settings.AllowTeamsConsumer + AllowPublicUsers = $Settings.AllowPublicUsers + AllowFederatedUsers = $AllowFederatedUsers + AllowedDomainsAsAList = $AllowedDomainsAsAList + BlockedDomains = $BlockedDomains + } + + try { + New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTenantFederationConfiguration' -CmdParams $cmdparams + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated Federation Configuration Policy' -sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Federation Configuration Policy. Error: $ErrorMessage" -sev Error + } + } + } + + if ($Settings.alert -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Federation Configuration is set correctly.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Federation Configuration is not set correctly.' -sev Alert + } + } + + if ($Setings.report -eq $true) { + Add-CIPPBPAField -FieldName 'FederationConfiguration' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 index 34a3d4060955..e0c747739a8e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 @@ -1,85 +1,88 @@ -Function Invoke-CIPPStandardTeamsGlobalMeetingPolicy { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) TeamsGlobalMeetingPolicy - .SYNOPSIS - (Label) Define Global Meeting Policy for Teams - .DESCRIPTION - (Helptext) Defines the CIS recommended global meeting policy for Teams. This includes AllowAnonymousUsersToJoinMeeting, AllowAnonymousUsersToStartMeeting, AutoAdmittedUsers, AllowPSTNUsersToBypassLobby, MeetingChatEnabledType, DesignatedPresenterRoleMode, AllowExternalParticipantGiveRequestControl - (DocsDescription) Defines the CIS recommended global meeting policy for Teams. This includes AllowAnonymousUsersToJoinMeeting, AllowAnonymousUsersToStartMeeting, AutoAdmittedUsers, AllowPSTNUsersToBypassLobby, MeetingChatEnabledType, DesignatedPresenterRoleMode, AllowExternalParticipantGiveRequestControl - .NOTES - CAT - Teams Standards - TAG - ADDEDCOMPONENT - {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.TeamsGlobalMeetingPolicy.DesignatedPresenterRoleMode","label":"Default value of the `Who can present?`","options":[{"label":"EveryoneUserOverride","value":"EveryoneUserOverride"},{"label":"EveryoneInCompanyUserOverride","value":"EveryoneInCompanyUserOverride"},{"label":"EveryoneInSameAndFederatedCompanyUserOverride","value":"EveryoneInSameAndFederatedCompanyUserOverride"},{"label":"OrganizerOnlyUserOverride","value":"OrganizerOnlyUserOverride"}]} - {"type":"switch","name":"standards.TeamsGlobalMeetingPolicy.AllowAnonymousUsersToJoinMeeting","label":"Allow anonymous users to join meeting"} - {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.TeamsGlobalMeetingPolicy.MeetingChatEnabledType","label":"Meeting chat policy","options":[{"label":"On for everyone","value":"Enabled"},{"label":"On for everyone but anonymous users","value":"EnabledExceptAnonymous"},{"label":"Off for everyone","value":"Disabled"}]} - IMPACT - Low Impact - POWERSHELLEQUIVALENT - Set-CsTeamsMeetingPolicy -AllowAnonymousUsersToJoinMeeting \$false -AllowAnonymousUsersToStartMeeting \$false -AutoAdmittedUsers EveryoneInCompanyExcludingGuests -AllowPSTNUsersToBypassLobby \$false -MeetingChatEnabledType EnabledExceptAnonymous -DesignatedPresenterRoleMode \$DesignatedPresenterRoleMode -AllowExternalParticipantGiveRequestControl \$false - RECOMMENDEDBY - "CIS 3.0" - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/teams-standards#low-impact - #> - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsGlobalMeetingPolicy' - - param($Tenant, $Settings) - $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsMeetingPolicy' -CmdParams @{Identity = 'Global' } - | Select-Object AllowAnonymousUsersToJoinMeeting, AllowAnonymousUsersToStartMeeting, AutoAdmittedUsers, AllowPSTNUsersToBypassLobby, MeetingChatEnabledType, DesignatedPresenterRoleMode, AllowExternalParticipantGiveRequestControl - - $MeetingChatEnabledType = $Settings.MeetingChatEnabledType.value ?? $Settings.MeetingChatEnabledType - $DesignatedPresenterRoleMode = $Settings.DesignatedPresenterRoleMode.value ?? $Settings.DesignatedPresenterRoleMode - - $StateIsCorrect = ($CurrentState.AllowAnonymousUsersToJoinMeeting -eq $Settings.AllowAnonymousUsersToJoinMeeting) -and - ($CurrentState.AllowAnonymousUsersToStartMeeting -eq $false) -and - ($CurrentState.AutoAdmittedUsers -eq 'EveryoneInCompanyExcludingGuests') -and - ($CurrentState.AllowPSTNUsersToBypassLobby -eq $false) -and - ($CurrentState.MeetingChatEnabledType -eq $MeetingChatEnabledType) -and - ($CurrentState.DesignatedPresenterRoleMode -eq $DesignatedPresenterRoleMode) -and - ($CurrentState.AllowExternalParticipantGiveRequestControl -eq $false) - - - if ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams Global Policy already set.' -sev Info - } else { - $cmdParams = @{ - Identity = 'Global' - AllowAnonymousUsersToJoinMeeting = $Settings.AllowAnonymousUsersToJoinMeeting - AllowAnonymousUsersToStartMeeting = $false - AutoAdmittedUsers = 'EveryoneInCompanyExcludingGuests' - AllowPSTNUsersToBypassLobby = $false - MeetingChatEnabledType = $MeetingChatEnabledType - DesignatedPresenterRoleMode = $DesignatedPresenterRoleMode - AllowExternalParticipantGiveRequestControl = $Settings.AllowExternalParticipantGiveRequestControl - } - - try { - New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTeamsMeetingPolicy' -CmdParams $cmdParams - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated Teams Global Policy' -sev Info - } catch { - $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Teams Global Policy. Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage - } - } - } - - if ($Settings.alert -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams Global Policy is set correctly.' -sev Info - } else { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams Global Policy is not set correctly.' -sev Alert - } - } - - if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'TeamsGlobalMeetingPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant - } -} +Function Invoke-CIPPStandardTeamsGlobalMeetingPolicy { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) TeamsGlobalMeetingPolicy + .SYNOPSIS + (Label) Define Global Meeting Policy for Teams + .DESCRIPTION + (Helptext) Defines the CIS recommended global meeting policy for Teams. This includes AllowAnonymousUsersToJoinMeeting, AllowAnonymousUsersToStartMeeting, AutoAdmittedUsers, AllowPSTNUsersToBypassLobby, MeetingChatEnabledType, DesignatedPresenterRoleMode, AllowExternalParticipantGiveRequestControl + (DocsDescription) Defines the CIS recommended global meeting policy for Teams. This includes AllowAnonymousUsersToJoinMeeting, AllowAnonymousUsersToStartMeeting, AutoAdmittedUsers, AllowPSTNUsersToBypassLobby, MeetingChatEnabledType, DesignatedPresenterRoleMode, AllowExternalParticipantGiveRequestControl + .NOTES + CAT + Teams Standards + TAG + ADDEDCOMPONENT + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.TeamsGlobalMeetingPolicy.DesignatedPresenterRoleMode","label":"Default value of the `Who can present?`","options":[{"label":"EveryoneUserOverride","value":"EveryoneUserOverride"},{"label":"EveryoneInCompanyUserOverride","value":"EveryoneInCompanyUserOverride"},{"label":"EveryoneInSameAndFederatedCompanyUserOverride","value":"EveryoneInSameAndFederatedCompanyUserOverride"},{"label":"OrganizerOnlyUserOverride","value":"OrganizerOnlyUserOverride"}]} + {"type":"switch","name":"standards.TeamsGlobalMeetingPolicy.AllowAnonymousUsersToJoinMeeting","label":"Allow anonymous users to join meeting"} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.TeamsGlobalMeetingPolicy.MeetingChatEnabledType","label":"Meeting chat policy","options":[{"label":"On for everyone","value":"Enabled"},{"label":"On for everyone but anonymous users","value":"EnabledExceptAnonymous"},{"label":"Off for everyone","value":"Disabled"}]} + {"type":"switch","name":"standards.TeamsGlobalMeetingPolicy.AllowExternalParticipantGiveRequestControl","label":"External participants can give or request control"} + IMPACT + Low Impact + ADDEDDATE + 2024-11-12 + POWERSHELLEQUIVALENT + Set-CsTeamsMeetingPolicy -AllowAnonymousUsersToJoinMeeting \$false -AllowAnonymousUsersToStartMeeting \$false -AutoAdmittedUsers EveryoneInCompanyExcludingGuests -AllowPSTNUsersToBypassLobby \$false -MeetingChatEnabledType EnabledExceptAnonymous -DesignatedPresenterRoleMode \$DesignatedPresenterRoleMode -AllowExternalParticipantGiveRequestControl \$false + RECOMMENDEDBY + "CIS 3.0" + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/teams-standards#low-impact + #> + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsGlobalMeetingPolicy' + + param($Tenant, $Settings) + $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsMeetingPolicy' -CmdParams @{Identity = 'Global' } + | Select-Object AllowAnonymousUsersToJoinMeeting, AllowAnonymousUsersToStartMeeting, AutoAdmittedUsers, AllowPSTNUsersToBypassLobby, MeetingChatEnabledType, DesignatedPresenterRoleMode, AllowExternalParticipantGiveRequestControl + + $MeetingChatEnabledType = $Settings.MeetingChatEnabledType.value ?? $Settings.MeetingChatEnabledType + $DesignatedPresenterRoleMode = $Settings.DesignatedPresenterRoleMode.value ?? $Settings.DesignatedPresenterRoleMode + + $StateIsCorrect = ($CurrentState.AllowAnonymousUsersToJoinMeeting -eq $Settings.AllowAnonymousUsersToJoinMeeting) -and + ($CurrentState.AllowAnonymousUsersToStartMeeting -eq $false) -and + ($CurrentState.AutoAdmittedUsers -eq 'EveryoneInCompanyExcludingGuests') -and + ($CurrentState.AllowPSTNUsersToBypassLobby -eq $false) -and + ($CurrentState.MeetingChatEnabledType -eq $MeetingChatEnabledType) -and + ($CurrentState.DesignatedPresenterRoleMode -eq $DesignatedPresenterRoleMode) -and + ($CurrentState.AllowExternalParticipantGiveRequestControl -eq $false) + + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams Global Policy already set.' -sev Info + } else { + $cmdParams = @{ + Identity = 'Global' + AllowAnonymousUsersToJoinMeeting = $Settings.AllowAnonymousUsersToJoinMeeting + AllowAnonymousUsersToStartMeeting = $false + AutoAdmittedUsers = 'EveryoneInCompanyExcludingGuests' + AllowPSTNUsersToBypassLobby = $false + MeetingChatEnabledType = $MeetingChatEnabledType + DesignatedPresenterRoleMode = $DesignatedPresenterRoleMode + AllowExternalParticipantGiveRequestControl = $Settings.AllowExternalParticipantGiveRequestControl + } + + try { + New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTeamsMeetingPolicy' -CmdParams $cmdParams + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated Teams Global Policy' -sev Info + } catch { + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to set Teams Global Policy. Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage + } + } + } + + if ($Settings.alert -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams Global Policy is set correctly.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams Global Policy is not set correctly.' -sev Alert + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'TeamsGlobalMeetingPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 index 9a3f94bb450f..c23c34f9ed9e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardTeamsMeetingsByDefault { {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.TeamsMeetingsByDefault.state","options":[{"label":"Enabled","value":"true"},{"label":"Disabled","value":"false"}]} IMPACT Low Impact + ADDEDDATE + 2024-05-31 POWERSHELLEQUIVALENT Set-OrganizationConfig -OnlineMeetingsByDefaultEnabled RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 index 56b13d7d967f..ca5c223d8ecc 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 @@ -1,100 +1,102 @@ -Function Invoke-CIPPStandardTeamsMessagingPolicy { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) TeamsMessagingPolicy - .SYNOPSIS - (Label) Global Messaging Policy for Microsoft Teams - .DESCRIPTION - (Helptext) Sets the properties of the Global messaging policy. - (DocsDescription) Sets the properties of the Global messaging policy. Messaging policies control which chat and channel messaging features are available to users in Teams. - .NOTES - CAT - Teams Standards - TAG - ADDEDCOMPONENT - {"type":"switch","name":"standards.TeamsMessagingPolicy.AllowOwnerDeleteMessage","label":"Allow Owner to Delete Messages","default":false} - {"type":"switch","name":"standards.TeamsMessagingPolicy.AllowUserDeleteMessage","label":"Allow User to Delete Messages","default":true} - {"type":"switch","name":"standards.TeamsMessagingPolicy.AllowUserEditMessage","label":"Allow User to Edit Messages","default":true} - {"type":"switch","name":"standards.TeamsMessagingPolicy.AllowUserDeleteChat","label":"Allow User to Delete Chats","default":true} - {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.TeamsMessagingPolicy.ReadReceiptsEnabledType","label":"Read Receipts Enabled Type","options":[{"label":"User controlled","value":"UserPreference"},{"label":"Turned on for everyone","value":"Everyone"},{"label":"Turned off for everyone","value":"None"}]} - {"type":"switch","name":"standards.TeamsMessagingPolicy.CreateCustomEmojis","label":"Allow Creating Custom Emojis","default":true} - {"type":"switch","name":"standards.TeamsMessagingPolicy.DeleteCustomEmojis","label":"Allow Deleting Custom Emojis","default":false} - {"type":"switch","name":"standards.TeamsMessagingPolicy.AllowSecurityEndUserReporting","label":"Allow reporting message as security concern","default":true} - {"type":"switch","name":"standards.TeamsMessagingPolicy.AllowCommunicationComplianceEndUserReporting","label":"Allow reporting message as inappropriate content","default":true} - IMPACT - Medium Impact - POWERSHELLEQUIVALENT - Set-CsTeamsMessagingPolicy - RECOMMENDEDBY - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/teams-standards#medium-impact - #> - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsMessagingPolicy' - - param($Tenant, $Settings) - $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsMessagingPolicy' -CmdParams @{Identity = 'Global' } - - if ($null -eq $Settings.AllowOwnerDeleteMessage) { $Settings.AllowOwnerDeleteMessage = $CurrentState.AllowOwnerDeleteMessage } - if ($null -eq $Settings.AllowUserDeleteMessage) { $Settings.AllowUserDeleteMessage = $CurrentState.AllowUserDeleteMessage } - if ($null -eq $Settings.AllowUserEditMessage) { $Settings.AllowUserEditMessage = $CurrentState.AllowUserEditMessage } - if ($null -eq $Settings.AllowUserDeleteChat) { $Settings.AllowUserDeleteChat = $CurrentState.AllowUserDeleteChat } - if ($null -eq $Settings.CreateCustomEmojis) { $Settings.CreateCustomEmojis = $CurrentState.CreateCustomEmojis } - if ($null -eq $Settings.DeleteCustomEmojis) { $Settings.DeleteCustomEmojis = $CurrentState.DeleteCustomEmojis } - if ($null -eq $Settings.AllowSecurityEndUserReporting) { $Settings.AllowSecurityEndUserReporting = $CurrentState.AllowSecurityEndUserReporting } - if ($null -eq $Settings.AllowCommunicationComplianceEndUserReporting) { $Settings.AllowCommunicationComplianceEndUserReporting = $CurrentState.AllowCommunicationComplianceEndUserReporting } - - $ReadReceiptsEnabledType = $Settings.ReadReceiptsEnabledType.value ?? $Settings.ReadReceiptsEnabledType - - $StateIsCorrect = ($CurrentState.AllowOwnerDeleteMessage -eq $Settings.AllowOwnerDeleteMessage) -and - ($CurrentState.AllowUserDeleteMessage -eq $Settings.AllowUserDeleteMessage) -and - ($CurrentState.AllowUserEditMessage -eq $Settings.AllowUserEditMessage) -and - ($CurrentState.AllowUserDeleteChat -eq $Settings.AllowUserDeleteChat) -and - ($CurrentState.ReadReceiptsEnabledType -eq $ReadReceiptsEnabledType) -and - ($CurrentState.CreateCustomEmojis -eq $Settings.CreateCustomEmojis) -and - ($CurrentState.DeleteCustomEmojis -eq $Settings.DeleteCustomEmojis) -and - ($CurrentState.AllowSecurityEndUserReporting -eq $Settings.AllowSecurityEndUserReporting) -and - ($CurrentState.AllowCommunicationComplianceEndUserReporting -eq $Settings.AllowCommunicationComplianceEndUserReporting) - - if ($Settings.remediate -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Global Teams Messaging policy already configured.' -sev Info - } else { - $cmdparams = @{ - Identity = 'Global' - AllowOwnerDeleteMessage = $Settings.AllowOwnerDeleteMessage - AllowUserDeleteMessage = $Settings.AllowUserDeleteMessage - AllowUserEditMessage = $Settings.AllowUserEditMessage - AllowUserDeleteChat = $Settings.AllowUserDeleteChat - ReadReceiptsEnabledType = $ReadReceiptsEnabledType - CreateCustomEmojis = $Settings.CreateCustomEmojis - DeleteCustomEmojis = $Settings.DeleteCustomEmojis - AllowSecurityEndUserReporting = $Settings.AllowSecurityEndUserReporting - AllowCommunicationComplianceEndUserReporting = $Settings.AllowCommunicationComplianceEndUserReporting - } - - try { - New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTeamsMessagingPolicy' -CmdParams $cmdparams - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated global Teams messaging policy' -sev Info - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Failed to configure global Teams messaging policy.' -sev Error -LogData $ErrorMessage - } - } - } - - if ($Settings.alert -eq $true) { - if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Global Teams messaging policy is configured correctly.' -sev Info - } else { - Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Global Teams messaging policy is not configured correctly.' -sev Alert - } - } - - if ($Setings.report -eq $true) { - Add-CIPPBPAField -FieldName 'TeamsMessagingPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant - } -} +Function Invoke-CIPPStandardTeamsMessagingPolicy { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) TeamsMessagingPolicy + .SYNOPSIS + (Label) Global Messaging Policy for Microsoft Teams + .DESCRIPTION + (Helptext) Sets the properties of the Global messaging policy. + (DocsDescription) Sets the properties of the Global messaging policy. Messaging policies control which chat and channel messaging features are available to users in Teams. + .NOTES + CAT + Teams Standards + TAG + ADDEDCOMPONENT + {"type":"switch","name":"standards.TeamsMessagingPolicy.AllowOwnerDeleteMessage","label":"Allow Owner to Delete Messages","defaultValue":false} + {"type":"switch","name":"standards.TeamsMessagingPolicy.AllowUserDeleteMessage","label":"Allow User to Delete Messages","defaultValue":true} + {"type":"switch","name":"standards.TeamsMessagingPolicy.AllowUserEditMessage","label":"Allow User to Edit Messages","defaultValue":true} + {"type":"switch","name":"standards.TeamsMessagingPolicy.AllowUserDeleteChat","label":"Allow User to Delete Chats","defaultValue":true} + {"type":"autoComplete","required":true,"multiple":false,"creatable":false,"name":"standards.TeamsMessagingPolicy.ReadReceiptsEnabledType","label":"Read Receipts Enabled Type","options":[{"label":"User controlled","value":"UserPreference"},{"label":"Turned on for everyone","value":"Everyone"},{"label":"Turned off for everyone","value":"None"}]} + {"type":"switch","name":"standards.TeamsMessagingPolicy.CreateCustomEmojis","label":"Allow Creating Custom Emojis","defaultValue":true} + {"type":"switch","name":"standards.TeamsMessagingPolicy.DeleteCustomEmojis","label":"Allow Deleting Custom Emojis","defaultValue":false} + {"type":"switch","name":"standards.TeamsMessagingPolicy.AllowSecurityEndUserReporting","label":"Allow reporting message as security concern","defaultValue":true} + {"type":"switch","name":"standards.TeamsMessagingPolicy.AllowCommunicationComplianceEndUserReporting","label":"Allow reporting message as inappropriate content","defaultValue":true} + IMPACT + Medium Impact + ADDEDDATE + 2025-01-10 + POWERSHELLEQUIVALENT + Set-CsTeamsMessagingPolicy + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/teams-standards#medium-impact + #> + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsMessagingPolicy' + + param($Tenant, $Settings) + $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsMessagingPolicy' -CmdParams @{Identity = 'Global' } + + if ($null -eq $Settings.AllowOwnerDeleteMessage) { $Settings.AllowOwnerDeleteMessage = $CurrentState.AllowOwnerDeleteMessage } + if ($null -eq $Settings.AllowUserDeleteMessage) { $Settings.AllowUserDeleteMessage = $CurrentState.AllowUserDeleteMessage } + if ($null -eq $Settings.AllowUserEditMessage) { $Settings.AllowUserEditMessage = $CurrentState.AllowUserEditMessage } + if ($null -eq $Settings.AllowUserDeleteChat) { $Settings.AllowUserDeleteChat = $CurrentState.AllowUserDeleteChat } + if ($null -eq $Settings.CreateCustomEmojis) { $Settings.CreateCustomEmojis = $CurrentState.CreateCustomEmojis } + if ($null -eq $Settings.DeleteCustomEmojis) { $Settings.DeleteCustomEmojis = $CurrentState.DeleteCustomEmojis } + if ($null -eq $Settings.AllowSecurityEndUserReporting) { $Settings.AllowSecurityEndUserReporting = $CurrentState.AllowSecurityEndUserReporting } + if ($null -eq $Settings.AllowCommunicationComplianceEndUserReporting) { $Settings.AllowCommunicationComplianceEndUserReporting = $CurrentState.AllowCommunicationComplianceEndUserReporting } + + $ReadReceiptsEnabledType = $Settings.ReadReceiptsEnabledType.value ?? $Settings.ReadReceiptsEnabledType + + $StateIsCorrect = ($CurrentState.AllowOwnerDeleteMessage -eq $Settings.AllowOwnerDeleteMessage) -and + ($CurrentState.AllowUserDeleteMessage -eq $Settings.AllowUserDeleteMessage) -and + ($CurrentState.AllowUserEditMessage -eq $Settings.AllowUserEditMessage) -and + ($CurrentState.AllowUserDeleteChat -eq $Settings.AllowUserDeleteChat) -and + ($CurrentState.ReadReceiptsEnabledType -eq $ReadReceiptsEnabledType) -and + ($CurrentState.CreateCustomEmojis -eq $Settings.CreateCustomEmojis) -and + ($CurrentState.DeleteCustomEmojis -eq $Settings.DeleteCustomEmojis) -and + ($CurrentState.AllowSecurityEndUserReporting -eq $Settings.AllowSecurityEndUserReporting) -and + ($CurrentState.AllowCommunicationComplianceEndUserReporting -eq $Settings.AllowCommunicationComplianceEndUserReporting) + + if ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Global Teams Messaging policy already configured.' -sev Info + } else { + $cmdparams = @{ + Identity = 'Global' + AllowOwnerDeleteMessage = $Settings.AllowOwnerDeleteMessage + AllowUserDeleteMessage = $Settings.AllowUserDeleteMessage + AllowUserEditMessage = $Settings.AllowUserEditMessage + AllowUserDeleteChat = $Settings.AllowUserDeleteChat + ReadReceiptsEnabledType = $ReadReceiptsEnabledType + CreateCustomEmojis = $Settings.CreateCustomEmojis + DeleteCustomEmojis = $Settings.DeleteCustomEmojis + AllowSecurityEndUserReporting = $Settings.AllowSecurityEndUserReporting + AllowCommunicationComplianceEndUserReporting = $Settings.AllowCommunicationComplianceEndUserReporting + } + + try { + New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTeamsMessagingPolicy' -CmdParams $cmdparams + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Updated global Teams messaging policy' -sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Failed to configure global Teams messaging policy.' -sev Error -LogData $ErrorMessage + } + } + } + + if ($Settings.alert -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Global Teams messaging policy is configured correctly.' -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Global Teams messaging policy is not configured correctly.' -sev Alert + } + } + + if ($Setings.report -eq $true) { + Add-CIPPBPAField -FieldName 'TeamsMessagingPolicy' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 index 5a6c9c956c1d..a65dd264850d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardTenantDefaultTimezone { {"type":"TimezoneSelect","name":"standards.TenantDefaultTimezone.Timezone","label":"Timezone"} IMPACT Low Impact + ADDEDDATE + 2024-04-20 POWERSHELLEQUIVALENT Update-MgBetaAdminSharePointSetting RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 index 89fb1db0b725..d7dd378a2562 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardTransportRuleTemplate { IMPACT Medium Impact + ADDEDDATE + 2023-12-30 ADDEDCOMPONENT {"type":"autoComplete","name":"transportRuleTemplate","label":"Select Transport Rule Template","api":{"url":"/api/ListTransportRulesTemplates","labelField":"name","valueField":"GUID","queryKey":"ListTransportRulesTemplates"}} UPDATECOMMENTBLOCK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUndoOauth.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUndoOauth.ps1 index 4eb46340bfe1..4840372a6166 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUndoOauth.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUndoOauth.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardUndoOauth { ADDEDCOMPONENT IMPACT High Impact + ADDEDDATE + 2022-01-07 POWERSHELLEQUIVALENT Update-MgPolicyAuthorizationPolicy RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 index ff74e6a0bda4..979a6d76d7ef 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 @@ -18,6 +18,8 @@ function Invoke-CIPPStandardUserSubmissions { {"type":"textField","name":"standards.UserSubmissions.email","required":false,"label":"Destination email address"} IMPACT Medium Impact + ADDEDDATE + 2024-06-28 POWERSHELLEQUIVALENT New-ReportSubmissionPolicy or Set-ReportSubmissionPolicy and New-ReportSubmissionRule or Set-ReportSubmissionRule RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOAuthTokens.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOAuthTokens.ps1 index f335ba4859e1..6b0cc1e1641d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOAuthTokens.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOAuthTokens.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardallowOAuthTokens { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2022-12-18 POWERSHELLEQUIVALENT Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOTPTokens.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOTPTokens.ps1 index a79bbd62a2e4..99383d1356ed 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOTPTokens.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardallowOTPTokens.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardallowOTPTokens { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2023-12-06 POWERSHELLEQUIVALENT Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 index dfac16a43399..908e76feb7d7 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 @@ -19,6 +19,8 @@ function Invoke-CIPPStandardcalDefault { {"type":"autoComplete","multiple":false,"label":"Select Sharing Level","name":"standards.calDefault.permissionLevel","options":[{"label":"Owner - The user can create, read, edit, and delete all items in the folder, and create subfolders. The user is both folder owner and folder contact.","value":"Owner"},{"label":"Publishing Editor - The user can create, read, edit, and delete all items in the folder, and create subfolders.","value":"PublishingEditor"},{"label":"Editor - The user can create items in the folder. The contents of the folder do not appear.","value":"Editor"},{"label":"Publishing Author. The user can read, create all items/subfolders. Can modify and delete only items they create.","value":"PublishingAuthor"},{"label":"Author - The user can create and read items, and modify and delete items that they create.","value":"Author"},{"label":"Non Editing Author - The user has full read access and create items. Can can delete only own items.","value":"NonEditingAuthor"},{"label":"Reviewer - The user can read all items in the folder.","value":"Reviewer"},{"label":"Contributor - The user can create items and folders.","value":"Contributor"},{"label":"Availability Only - Indicates that the user can view only free/busy time within the calendar.","value":"AvailabilityOnly"},{"label":"Limited Details - The user can view free/busy time within the calendar and the subject and location of appointments.","value":"LimitedDetails"},{"label":"None - The user has no permissions on the folder.","value":"none"}]} IMPACT Low Impact + ADDEDDATE + 2023-04-27 POWERSHELLEQUIVALENT Set-MailboxFolderPermission RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 index 50c59494e277..bfa15dd5d440 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandarddisableMacSync { ADDEDCOMPONENT IMPACT High Impact + ADDEDDATE + 2022-06-15 POWERSHELLEQUIVALENT Update-MgAdminSharePointSetting RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneBrandingProfile.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneBrandingProfile.ps1 index 95289a2fa964..ac60619aef3e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneBrandingProfile.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneBrandingProfile.ps1 @@ -1,100 +1,102 @@ -function Invoke-CIPPStandardintuneBrandingProfile { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) intuneBrandingProfile - .SYNOPSIS - (Label) Set Intune Company Portal branding profile - .DESCRIPTION - (Helptext) Sets the branding profile for the Intune Company Portal app. This is a tenant wide setting and overrules any settings set on the app level. - (DocsDescription) Sets the branding profile for the Intune Company Portal app. This is a tenant wide setting and overrules any settings set on the app level. - .NOTES - CAT - Intune Standards - TAG - ADDEDCOMPONENT - {"type":"textField","name":"standards.intuneBrandingProfile.displayName","label":"Organization name","required":false} - {"type":"switch","name":"standards.intuneBrandingProfile.showLogo","label":"Show logo"} - {"type":"switch","name":"standards.intuneBrandingProfile.showDisplayNameNextToLogo","label":"Show organization name next to logo","required":false} - {"type":"textField","name":"standards.intuneBrandingProfile.contactITName","label":"Contact IT name","required":false} - {"type":"textField","name":"standards.intuneBrandingProfile.contactITPhoneNumber","label":"Contact IT phone number","required":false} - {"type":"textField","name":"standards.intuneBrandingProfile.contactITEmailAddress","label":"Contact IT email address","required":false} - {"type":"textField","name":"standards.intuneBrandingProfile.contactITNotes","label":"Contact IT notes","required":false} - {"type":"textField","name":"standards.intuneBrandingProfile.onlineSupportSiteName","label":"Online support site name","required":false} - {"type":"textField","name":"standards.intuneBrandingProfile.onlineSupportSiteUrl","label":"Online support site URL","required":false} - {"type":"textField","name":"standards.intuneBrandingProfile.privacyUrl","label":"Privacy statement URL","required":false} - IMPACT - Low Impact - POWERSHELLEQUIVALENT - Graph API - RECOMMENDEDBY - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/intune-standards#low-impact - #> - - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'intuneBrandingProfile' - - $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 - } -} +function Invoke-CIPPStandardintuneBrandingProfile { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) intuneBrandingProfile + .SYNOPSIS + (Label) Set Intune Company Portal branding profile + .DESCRIPTION + (Helptext) Sets the branding profile for the Intune Company Portal app. This is a tenant wide setting and overrules any settings set on the app level. + (DocsDescription) Sets the branding profile for the Intune Company Portal app. This is a tenant wide setting and overrules any settings set on the app level. + .NOTES + CAT + Intune Standards + TAG + ADDEDCOMPONENT + {"type":"textField","name":"standards.intuneBrandingProfile.displayName","label":"Organization name","required":false} + {"type":"switch","name":"standards.intuneBrandingProfile.showLogo","label":"Show logo"} + {"type":"switch","name":"standards.intuneBrandingProfile.showDisplayNameNextToLogo","label":"Show organization name next to logo","required":false} + {"type":"textField","name":"standards.intuneBrandingProfile.contactITName","label":"Contact IT name","required":false} + {"type":"textField","name":"standards.intuneBrandingProfile.contactITPhoneNumber","label":"Contact IT phone number","required":false} + {"type":"textField","name":"standards.intuneBrandingProfile.contactITEmailAddress","label":"Contact IT email address","required":false} + {"type":"textField","name":"standards.intuneBrandingProfile.contactITNotes","label":"Contact IT notes","required":false} + {"type":"textField","name":"standards.intuneBrandingProfile.onlineSupportSiteName","label":"Online support site name","required":false} + {"type":"textField","name":"standards.intuneBrandingProfile.onlineSupportSiteUrl","label":"Online support site URL","required":false} + {"type":"textField","name":"standards.intuneBrandingProfile.privacyUrl","label":"Privacy statement URL","required":false} + IMPACT + Low Impact + ADDEDDATE + 2024-06-20 + POWERSHELLEQUIVALENT + Graph API + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/intune-standards#low-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'intuneBrandingProfile' + + $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-CIPPStandardintuneDeviceReg.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 index 2103a785915e..bd58f15be325 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardintuneDeviceReg { {"type":"number","name":"standards.intuneDeviceReg.max","label":"Maximum devices (Enter 2147483647 for unlimited.)","required":true} IMPACT Medium Impact + ADDEDDATE + 2023-03-27 POWERSHELLEQUIVALENT Update-MgBetaPolicyDeviceRegistrationPolicy RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 index 34ac3bb23102..6705a03031e6 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 @@ -17,6 +17,8 @@ function Invoke-CIPPStandardintuneDeviceRetirementDays { {"type":"number","name":"standards.intuneDeviceRetirementDays.days","label":"Maximum days (0 equals disabled)"} IMPACT Low Impact + ADDEDDATE + 2023-05-19 POWERSHELLEQUIVALENT Graph API RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 index 26e60d4930d5..e898d3e88d0a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 @@ -15,6 +15,8 @@ function Invoke-CIPPStandardintuneRequireMFA { TAG IMPACT Medium Impact + ADDEDDATE + 2023-10-23 POWERSHELLEQUIVALENT Update-MgBetaPolicyDeviceRegistrationPolicy RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardlaps.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardlaps.ps1 index 9b30858e3675..866fabf1043c 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardlaps.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardlaps.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardlaps { ADDEDCOMPONENT IMPACT Low Impact + ADDEDDATE + 2023-04-25 POWERSHELLEQUIVALENT Portal or Graph API RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 index 7a4e443d7962..4369a0c46b14 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 @@ -18,6 +18,8 @@ function Invoke-CIPPStandardsharingCapability { {"type":"autoComplete","multiple":false,"label":"Select Sharing Level","name":"standards.sharingCapability.Level","options":[{"label":"Users can share only with people in the organization. No external sharing is allowed.","value":"disabled"},{"label":"Users can share with new and existing guests. Guests must sign in or provide a verification code.","value":"externalUserSharingOnly"},{"label":"Users can share with anyone by using links that do not require sign-in.","value":"externalUserAndGuestSharing"},{"label":"Users can share with existing guests (those already in the directory of the organization).","value":"existingExternalUserSharingOnly"}]} IMPACT High Impact + ADDEDDATE + 2022-06-15 POWERSHELLEQUIVALENT Update-MgBetaAdminSharePointSetting RECOMMENDEDBY diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingDomainRestriction.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingDomainRestriction.ps1 index 32b74e3b1780..079b6e319d3a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingDomainRestriction.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingDomainRestriction.ps1 @@ -1,92 +1,94 @@ -function Invoke-CIPPStandardsharingDomainRestriction { - <# - .FUNCTIONALITY - Internal - .COMPONENT - (APIName) sharingDomainRestriction - .SYNOPSIS - (Label) Restrict sharing to a specific domain - .DESCRIPTION - (Helptext) Restricts sharing to only users with the specified domain. This is useful for organizations that only want to share with their own domain. - (DocsDescription) Restricts sharing to only users with the specified domain. This is useful for organizations that only want to share with their own domain. - .NOTES - CAT - SharePoint Standards - TAG - "CIS" - ADDEDCOMPONENT - {"type":"autoComplete","multiple":false,"name":"standards.sharingDomainRestriction.Mode","label":"Limit external sharing by domains","options":[{"label":"Off","value":"none"},{"label":"Restrict sharing to specific domains","value":"allowList"},{"label":"Block sharing to specific domains","value":"blockList"}]} - {"type":"textField","name":"standards.sharingDomainRestriction.Domains","label":"Domains to allow/block, comma separated","required":false} - IMPACT - High Impact - POWERSHELLEQUIVALENT - Update-MgAdminSharePointSetting - RECOMMENDEDBY - UPDATECOMMENTBLOCK - Run the Tools\Update-StandardsComments.ps1 script to update this comment block - .LINK - https://docs.cipp.app/user-documentation/tenant/standards/list-standards/sharepoint-standards#high-impact - #> - - param($Tenant, $Settings) - ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'sharingDomainRestriction' - - $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true - - # Get mode value using null-coalescing operator - $mode = $Settings.Mode.value ?? $Settings.Mode - - if ($mode -eq 'none' -or $null -eq $mode) { - $StateIsCorrect = $CurrentState.sharingDomainRestrictionMode -eq 'none' - } else { - $SelectedDomains = [String[]]$Settings.Domains.Split(',').Trim() - $StateIsCorrect = ($CurrentState.sharingDomainRestrictionMode -eq $mode) -and - ($mode -eq 'allowList' -and (!(Compare-Object -ReferenceObject $CurrentState.sharingAllowedDomainList -DifferenceObject $SelectedDomains))) -or - ($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 = $mode - } - - if ($mode -eq 'AllowList') { - $Body.Add('sharingAllowedDomainList', $SelectedDomains) - } elseif ($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 { - $null = New-GraphPostRequest @cmdParams - Write-LogMessage -API 'Standards' -tenant $tenant -message 'Successfully updated Sharing Domain Restriction settings' -sev Info - } catch { - $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to update Sharing Domain Restriction settings. Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage - } - } - } - - 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 - } -} +function Invoke-CIPPStandardsharingDomainRestriction { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) sharingDomainRestriction + .SYNOPSIS + (Label) Restrict sharing to a specific domain + .DESCRIPTION + (Helptext) Restricts sharing to only users with the specified domain. This is useful for organizations that only want to share with their own domain. + (DocsDescription) Restricts sharing to only users with the specified domain. This is useful for organizations that only want to share with their own domain. + .NOTES + CAT + SharePoint Standards + TAG + "CIS" + ADDEDCOMPONENT + {"type":"autoComplete","multiple":false,"name":"standards.sharingDomainRestriction.Mode","label":"Limit external sharing by domains","options":[{"label":"Off","value":"none"},{"label":"Restrict sharing to specific domains","value":"allowList"},{"label":"Block sharing to specific domains","value":"blockList"}]} + {"type":"textField","name":"standards.sharingDomainRestriction.Domains","label":"Domains to allow/block, comma separated","required":false} + IMPACT + High Impact + ADDEDDATE + 2024-06-20 + POWERSHELLEQUIVALENT + Update-MgAdminSharePointSetting + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/sharepoint-standards#high-impact + #> + + param($Tenant, $Settings) + ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'sharingDomainRestriction' + + $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true + + # Get mode value using null-coalescing operator + $mode = $Settings.Mode.value ?? $Settings.Mode + + if ($mode -eq 'none' -or $null -eq $mode) { + $StateIsCorrect = $CurrentState.sharingDomainRestrictionMode -eq 'none' + } else { + $SelectedDomains = [String[]]$Settings.Domains.Split(',').Trim() + $StateIsCorrect = ($CurrentState.sharingDomainRestrictionMode -eq $mode) -and + ($mode -eq 'allowList' -and (!(Compare-Object -ReferenceObject $CurrentState.sharingAllowedDomainList -DifferenceObject $SelectedDomains))) -or + ($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 = $mode + } + + if ($mode -eq 'AllowList') { + $Body.Add('sharingAllowedDomainList', $SelectedDomains) + } elseif ($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 { + $null = New-GraphPostRequest @cmdParams + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Successfully updated Sharing Domain Restriction settings' -sev Info + } catch { + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to update Sharing Domain Restriction settings. Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage + } + } + } + + 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/Standards/Invoke-CIPPStandardunmanagedSync.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardunmanagedSync.ps1 index 15547c8893ce..7b0d2b43b2cb 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardunmanagedSync.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardunmanagedSync.ps1 @@ -16,6 +16,8 @@ function Invoke-CIPPStandardunmanagedSync { ADDEDCOMPONENT IMPACT High Impact + ADDEDDATE + 2022-06-15 POWERSHELLEQUIVALENT Update-MgAdminSharePointSetting RECOMMENDEDBY From 41d5c0331e90ebe2e2cd5cbc637e286bd9941b52 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 25 Feb 2025 15:17:22 -0500 Subject: [PATCH 070/167] parameter splat cleanup Remove null/blank/empty values --- Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 b/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 index ed2bfd4da7c0..f4c22a7e626e 100644 --- a/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 +++ b/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 @@ -23,6 +23,10 @@ function Add-CIPPScheduledTask { $Parameters = [System.Collections.Hashtable]@{} foreach ($Key in $task.Parameters.PSObject.Properties.Name) { $Param = $task.Parameters.$Key + + if ($null -eq $Param -or $Param -eq '' -or ($Param | Measure-Object).Count -eq 0) { + continue + } if ($Param -is [System.Collections.IDictionary] -or $Param.Key) { $ht = @{} foreach ($p in $Param.GetEnumerator()) { From f60d0a78cb52ae2af2eaa326ad4d7beb6f2d86e1 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 25 Feb 2025 15:46:07 -0500 Subject: [PATCH 071/167] prevent errors when no webhooks to renew --- .../Invoke-CIPPGraphWebhookRenewal.ps1 | 68 ++++++++++--------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/Modules/CIPPCore/Public/Webhooks/Invoke-CIPPGraphWebhookRenewal.ps1 b/Modules/CIPPCore/Public/Webhooks/Invoke-CIPPGraphWebhookRenewal.ps1 index 16f7890c4e94..5ff8f3631212 100644 --- a/Modules/CIPPCore/Public/Webhooks/Invoke-CIPPGraphWebhookRenewal.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/Invoke-CIPPGraphWebhookRenewal.ps1 @@ -1,45 +1,47 @@ function Invoke-CippGraphWebhookRenewal { - $RenewalDate = (Get-Date).AddDays(1).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ") + $RenewalDate = (Get-Date).AddDays(1).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss.fffZ') $body = @{ - "expirationDateTime" = "$RenewalDate" + 'expirationDateTime' = "$RenewalDate" } | ConvertTo-Json - $WebhookTable = Get-CIPPTable -TableName webhookTable - $WebhookData = Get-AzDataTableEntity @WebhookTable | Where-Object { $null -ne $_.SubscriptionID -and $_.SubscriptionID -ne '' -and ((Get-Date($_.Expiration)) -le ((Get-Date).AddHours(2))) } + try { + $WebhookData = Get-AzDataTableEntity @WebhookTable | Where-Object { $null -ne $_.SubscriptionID -and $_.SubscriptionID -ne '' -and ((Get-Date($_.Expiration)) -le ((Get-Date).AddHours(2))) } + } catch { + $WebhookData = @() + } - foreach ($UpdateSub in $WebhookData) { - try { - $TenantFilter = $UpdateSub.PartitionKey + if (($WebhookData | Measure-Object).Count -gt 0) { + foreach ($UpdateSub in $WebhookData) { try { - $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/subscriptions/$($UpdateSub.SubscriptionID)" -tenantid $TenantFilter -type PATCH -body $body -Verbose - $UpdateSub.Expiration = $RenewalDate - $null = Add-AzDataTableEntity @WebhookTable -Entity $UpdateSub -Force - Write-LogMessage -Headers'CIPP' -API 'Renew_Graph_Subscriptions' -message "Renewed Subscription:$($UpdateSub.SubscriptionID)" -Sev "Info" -tenant $TenantFilter - - } catch { - # Rebuild creation parameters - $BaseURL = "$(([uri]($UpdateSub.WebhookNotificationUrl)).Host)" - if ($UpdateSub.TypeofSubscription) { - $TypeofSubscription = "$($UpdateSub.TypeofSubscription)" - } else { - $TypeofSubscription = 'updated' + $TenantFilter = $UpdateSub.PartitionKey + try { + $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/subscriptions/$($UpdateSub.SubscriptionID)" -tenantid $TenantFilter -type PATCH -body $body -Verbose + $UpdateSub.Expiration = $RenewalDate + $null = Add-AzDataTableEntity @WebhookTable -Entity $UpdateSub -Force + Write-LogMessage -API 'Renew_Graph_Subscriptions' -message "Renewed Subscription:$($UpdateSub.SubscriptionID)" -Sev 'Info' -tenant $TenantFilter + + } catch { + # Rebuild creation parameters + $BaseURL = "$(([uri]($UpdateSub.WebhookNotificationUrl)).Host)" + if ($UpdateSub.TypeofSubscription) { + $TypeofSubscription = "$($UpdateSub.TypeofSubscription)" + } else { + $TypeofSubscription = 'updated' + } + $Resource = "$($UpdateSub.Resource)" + $EventType = "$($UpdateSub.EventType)" + + Write-LogMessage -API 'Renew_Graph_Subscriptions' -message "Recreating: $($UpdateSub.SubscriptionID) as renewal failed." -Sev 'Info' -tenant $TenantFilter + $CreateResult = New-CIPPGraphSubscription -TenantFilter $TenantFilter -TypeofSubscription $TypeofSubscription -BaseURL $BaseURL -Resource $Resource -EventType $EventType -Headers 'GraphSubscriptionRenewal' -Recreate + + if ($CreateResult -match 'Created Webhook subscription for') { + Remove-AzDataTableEntity -Force @WebhookTable -Entity $UpdateSub + } } - $Resource = "$($UpdateSub.Resource)" - $EventType = "$($UpdateSub.EventType)" - - Write-LogMessage -Headers'CIPP' -API 'Renew_Graph_Subscriptions' -message "Recreating: $($UpdateSub.SubscriptionID) as renewal failed." -Sev "Info" -tenant $TenantFilter - $CreateResult = New-CIPPGraphSubscription -TenantFilter $TenantFilter -TypeofSubscription $TypeofSubscription -BaseURL $BaseURL -Resource $Resource -EventType $EventType -Headers 'GraphSubscriptionRenewal' -Recreate - - if ($CreateResult -match 'Created Webhook subscription for') { - Remove-AzDataTableEntity -Force @WebhookTable -Entity $UpdateSub - } - + } catch { + Write-LogMessage -API 'Renew_Graph_Subscriptions' -message "Failed to renew Webhook Subscription: $($UpdateSub.SubscriptionID). Linenumber: $($_.InvocationInfo.ScriptLineNumber) Error: $($_.Exception.message)" -Sev 'Error' -tenant $TenantFilter } - - - } catch { - Write-LogMessage -Headers'CIPP' -API 'Renew_Graph_Subscriptions' -message "Failed to renew Webhook Subscription: $($UpdateSub.SubscriptionID). Linenumber: $($_.InvocationInfo.ScriptLineNumber) Error: $($_.Exception.message)" -Sev "Error" -tenant $TenantFilter } } } From af24918ec9ed03638a736bd9180dcef24bcd91ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Tue, 25 Feb 2025 22:27:38 +0100 Subject: [PATCH 072/167] fix: enhance logging for API access and standardize variable usage across multiple functions --- .../Extensions/Invoke-ListExtensionSync.ps1 | 5 ++- .../CIPP/Settings/Invoke-ListCustomRole.ps1 | 4 +++ .../Invoke-ListCalendarPermissions.ps1 | 16 ++++++---- .../Invoke-ListConnectionFilterTemplates.ps1 | 3 +- .../Email-Exchange/Invoke-ListExoRequest.ps1 | 5 +++ .../Invoke-ListApplicationQueue.ps1 | 7 ++-- .../Invoke-ListAppsRepository.ps1 | 3 +- .../Alerts/Invoke-ListAlertsQueue.ps1 | 5 ++- .../Alerts/Invoke-ListAuditLogSearches.ps1 | 32 +++++++++++++------ .../GDAP/Invoke-ListGDAPAccessAssignments.ps1 | 4 +++ .../Invoke-ListGenericAllTenants.ps1 | 3 ++ .../Invoke-ListGenericTestFunction.ps1 | 5 +-- 12 files changed, 62 insertions(+), 30 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ListExtensionSync.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ListExtensionSync.ps1 index 0f8aa6c2bc77..2ae14ac3a13c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ListExtensionSync.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ListExtensionSync.ps1 @@ -11,10 +11,9 @@ Function Invoke-ListExtensionSync { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' $ScheduledTasksTable = Get-CIPPTable -TableName 'ScheduledTasks' $ScheduledTasks = Get-CIPPAzDataTableEntity @ScheduledTasksTable -Filter 'Hidden eq true' | Where-Object { $_.Command -match 'CippExtension' } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ListCustomRole.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ListCustomRole.ps1 index 284be3d8095c..0d98b1797043 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ListCustomRole.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ListCustomRole.ps1 @@ -8,6 +8,10 @@ function Invoke-ListCustomRole { [CmdletBinding()] param($Request, $TriggerMetadata) + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $Table = Get-CippTable -tablename 'CustomRoles' $Body = Get-CIPPAzDataTableEntity @Table diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListCalendarPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListCalendarPermissions.ps1 index a4640809048f..45412db74533 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListCalendarPermissions.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListCalendarPermissions.ps1 @@ -11,16 +11,20 @@ Function Invoke-ListCalendarPermissions { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - $UserID = $request.Query.UserID - $Tenantfilter = $request.Query.tenantfilter + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + $UserID = $Request.Query.UserID + $TenantFilter = $Request.Query.tenantFilter try { $GetCalParam = @{Identity = $UserID; FolderScope = 'Calendar' } - $CalendarFolder = New-ExoRequest -tenantid $Tenantfilter -cmdlet 'Get-MailboxFolderStatistics' -anchor $UserID -cmdParams $GetCalParam | Select-Object -First 1 + $CalendarFolder = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-MailboxFolderStatistics' -anchor $UserID -cmdParams $GetCalParam | Select-Object -First 1 -ExcludeProperty *data.type* $CalParam = @{Identity = "$($UserID):\$($CalendarFolder.name)" } - $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 + $GraphRequest = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-MailboxFolderPermission' -anchor $UserID -cmdParams $CalParam -UseSystemMailbox $true | Select-Object Identity, User, AccessRights, FolderName + $GraphRequest | Add-Member -MemberType NoteProperty -Name 'UserID' -Value $UserID + $GraphRequest | Add-Member -MemberType NoteProperty -Name 'ExchangeGUID' -Value $CalendarFolder.ContentMailboxGuid + Write-LogMessage -API $APIName -tenant $TenantFilter -message "Calendar permissions listed for $($TenantFilter)" -sev Debug $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListConnectionFilterTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListConnectionFilterTemplates.ps1 index 08d32756da2f..b799ab74a6e1 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListConnectionFilterTemplates.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListConnectionFilterTemplates.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListConnectionFilterTemplates { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' $Table = Get-CippTable -tablename 'templates' #List new policies diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListExoRequest.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListExoRequest.ps1 index 6e31de2403ce..c64c99a7ee92 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListExoRequest.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListExoRequest.ps1 @@ -1,6 +1,10 @@ function Invoke-ListExoRequest { param($Request, $TriggerMetadata) + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + try { $AllowedVerbs = @( 'Get' @@ -12,6 +16,7 @@ function Invoke-ListExoRequest { $Verb = ($Cmdlet -split '-')[0] $AllowedTenants = Test-CIPPAccess -Request $Request -TenantList + $TenantFilter = $Request.Body.TenantFilter $Tenants = Get-Tenants -IncludeErrors $Tenant = $Tenants | Where-Object { $_.defaultDomainName -eq $TenantFilter -or $_.customerId -eq $TenantFilter } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApplicationQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApplicationQueue.ps1 index 9fc4e3200ea5..a1109f79386a 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApplicationQueue.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApplicationQueue.ps1 @@ -11,11 +11,10 @@ Function Invoke-ListApplicationQueue { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' $Table = Get-CippTable -tablename 'apps' $QueuedApps = (Get-CIPPAzDataTableEntity @Table) @@ -24,7 +23,7 @@ Function Invoke-ListApplicationQueue { $ApplicationFile = $QueueFile.JSON | ConvertFrom-Json -Depth 10 [PSCustomObject]@{ tenantName = $ApplicationFile.tenant - applicationName = $ApplicationFile.Applicationname + applicationName = $ApplicationFile.applicationName cmdLine = $ApplicationFile.IntuneBody.installCommandLine assignTo = $ApplicationFile.assignTo id = $($QueueFile.RowKey) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListAppsRepository.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListAppsRepository.ps1 index 685d06eacf37..3048b6789138 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListAppsRepository.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListAppsRepository.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListAppsRepository { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' $Search = $Request.Body.Search $Repository = $Request.Body.Repository diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAlertsQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAlertsQueue.ps1 index 460a36ad70a5..8d4436ef3412 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAlertsQueue.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAlertsQueue.ps1 @@ -11,11 +11,10 @@ Function Invoke-ListAlertsQueue { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' $WebhookTable = Get-CIPPTable -TableName 'WebhookRules' $WebhookRules = Get-CIPPAzDataTableEntity @WebhookTable diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAuditLogSearches.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAuditLogSearches.ps1 index 561384504174..4468443aece3 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAuditLogSearches.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAuditLogSearches.ps1 @@ -7,36 +7,48 @@ function Invoke-ListAuditLogSearches { #> Param($Request, $TriggerMetadata) - if ($Request.Query.TenantFilter) { - switch ($Request.Query.Type) { + + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + # Interact with the query parameters + $TenantFilter = $Request.Query.tenantFilter + $SearchId = $Request.Query.SearchId + $Days = $Request.Query.Days + $Type = $Request.Query.Type + + + if ($TenantFilter) { + switch ($Type) { 'Searches' { - $Results = Get-CippAuditLogSearches -TenantFilter $Request.Query.TenantFilter + $Results = Get-CippAuditLogSearches -TenantFilter $TenantFilter $Body = @{ Results = @($Results) Metadata = @{ - TenantFilter = $Request.Query.TenantFilter + TenantFilter = $TenantFilter TotalSearches = $Results.Count } } | ConvertTo-Json -Depth 10 -Compress } 'SearchResults' { try { - $Results = Get-CippAuditLogSearchResults -TenantFilter $Request.Query.TenantFilter -QueryId $Request.Query.SearchId + $Results = Get-CippAuditLogSearchResults -TenantFilter $TenantFilter -QueryId $SearchId } catch { $Results = @{ Error = $_.Exception.Message } } $Body = @{ Results = @($Results) Metadata = @{ - SearchId = $Request.Query.SearchId - TenantFilter = $Request.Query.TenantFilter + SearchId = $SearchId + TenantFilter = $TenantFilter TotalResults = $Results.Count } } | ConvertTo-Json -Depth 10 -Compress } default { - if ($Request.Query.Days) { - $Days = $Request.Query.Days + if ($Days) { + $Days = $Days } else { $Days = 1 } @@ -62,7 +74,7 @@ function Invoke-ListAuditLogSearches { Results = @($Results) Metadata = @{ StartTime = $StartTime - TenantFilter = $Request.Query.TenantFilter + TenantFilter = $TenantFilter } } | ConvertTo-Json -Depth 10 -Compress } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPAccessAssignments.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPAccessAssignments.ps1 index 83fae86a70ea..953e87831000 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPAccessAssignments.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPAccessAssignments.ps1 @@ -6,6 +6,10 @@ function Invoke-ListGDAPAccessAssignments { [CmdletBinding()] param($Request, $TriggerMetadata) + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $Id = $Request.Query.Id $TenantFilter = $env:TenantID diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericAllTenants.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericAllTenants.ps1 index f579777b5607..e8cdc66c8df8 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericAllTenants.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericAllTenants.ps1 @@ -10,6 +10,9 @@ Function Invoke-ListGenericAllTenants { [CmdletBinding()] param($Request, $TriggerMetadata) + + # XXX This feels like an unused endpoint to me. -Bobby + $TableURLName = ($QueueItem.tolower().split('?').Split('/') | Select-Object -First 1).toString() $QueueKey = (Invoke-ListCippQueue | Where-Object -Property Name -EQ $TableURLName | Select-Object -Last 1).RowKey Update-CippQueueEntry -RowKey $QueueKey -Status 'Started' diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericTestFunction.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericTestFunction.ps1 index cea9da93182e..bb2172b2ec95 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericTestFunction.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericTestFunction.ps1 @@ -11,8 +11,9 @@ Function Invoke-ListGenericTestFunction { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - $graphRequest = ($request.headers.'x-ms-original-url').split('/api') | Select-Object -First 1 + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $graphRequest = ($Headers.'x-ms-original-url').split('/api') | Select-Object -First 1 Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK From 7af823b49b2466d595ae3e0fc7b4c3464fbb0f57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Tue, 25 Feb 2025 19:15:42 +0100 Subject: [PATCH 073/167] fix: standardize variable naming and improve error handling in Invoke-RemoveApp function fix: enhance logging for API access and standardize variable usage across multiple functions --- .../Extensions/Invoke-ListExtensionSync.ps1 | 5 ++- .../CIPP/Settings/Invoke-ListCustomRole.ps1 | 4 +++ .../Invoke-ListCalendarPermissions.ps1 | 16 ++++++---- .../Invoke-ListConnectionFilterTemplates.ps1 | 3 +- .../Email-Exchange/Invoke-ListExoRequest.ps1 | 5 +++ .../Invoke-ListApplicationQueue.ps1 | 7 ++-- .../Invoke-ListAppsRepository.ps1 | 3 +- .../Applications/Invoke-RemoveApp.ps1 | 19 +++++------ .../Alerts/Invoke-ListAlertsQueue.ps1 | 5 ++- .../Alerts/Invoke-ListAuditLogSearches.ps1 | 32 +++++++++++++------ .../GDAP/Invoke-ListGDAPAccessAssignments.ps1 | 4 +++ .../Invoke-ListGenericAllTenants.ps1 | 3 ++ .../Invoke-ListGenericTestFunction.ps1 | 5 +-- 13 files changed, 72 insertions(+), 39 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ListExtensionSync.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ListExtensionSync.ps1 index 0f8aa6c2bc77..2ae14ac3a13c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ListExtensionSync.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ListExtensionSync.ps1 @@ -11,10 +11,9 @@ Function Invoke-ListExtensionSync { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' $ScheduledTasksTable = Get-CIPPTable -TableName 'ScheduledTasks' $ScheduledTasks = Get-CIPPAzDataTableEntity @ScheduledTasksTable -Filter 'Hidden eq true' | Where-Object { $_.Command -match 'CippExtension' } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ListCustomRole.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ListCustomRole.ps1 index 284be3d8095c..0d98b1797043 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ListCustomRole.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ListCustomRole.ps1 @@ -8,6 +8,10 @@ function Invoke-ListCustomRole { [CmdletBinding()] param($Request, $TriggerMetadata) + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $Table = Get-CippTable -tablename 'CustomRoles' $Body = Get-CIPPAzDataTableEntity @Table diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListCalendarPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListCalendarPermissions.ps1 index a4640809048f..45412db74533 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListCalendarPermissions.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListCalendarPermissions.ps1 @@ -11,16 +11,20 @@ Function Invoke-ListCalendarPermissions { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - $UserID = $request.Query.UserID - $Tenantfilter = $request.Query.tenantfilter + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + $UserID = $Request.Query.UserID + $TenantFilter = $Request.Query.tenantFilter try { $GetCalParam = @{Identity = $UserID; FolderScope = 'Calendar' } - $CalendarFolder = New-ExoRequest -tenantid $Tenantfilter -cmdlet 'Get-MailboxFolderStatistics' -anchor $UserID -cmdParams $GetCalParam | Select-Object -First 1 + $CalendarFolder = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-MailboxFolderStatistics' -anchor $UserID -cmdParams $GetCalParam | Select-Object -First 1 -ExcludeProperty *data.type* $CalParam = @{Identity = "$($UserID):\$($CalendarFolder.name)" } - $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 + $GraphRequest = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-MailboxFolderPermission' -anchor $UserID -cmdParams $CalParam -UseSystemMailbox $true | Select-Object Identity, User, AccessRights, FolderName + $GraphRequest | Add-Member -MemberType NoteProperty -Name 'UserID' -Value $UserID + $GraphRequest | Add-Member -MemberType NoteProperty -Name 'ExchangeGUID' -Value $CalendarFolder.ContentMailboxGuid + Write-LogMessage -API $APIName -tenant $TenantFilter -message "Calendar permissions listed for $($TenantFilter)" -sev Debug $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListConnectionFilterTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListConnectionFilterTemplates.ps1 index 08d32756da2f..b799ab74a6e1 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListConnectionFilterTemplates.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListConnectionFilterTemplates.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListConnectionFilterTemplates { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' $Table = Get-CippTable -tablename 'templates' #List new policies diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListExoRequest.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListExoRequest.ps1 index 6e31de2403ce..c64c99a7ee92 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListExoRequest.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListExoRequest.ps1 @@ -1,6 +1,10 @@ function Invoke-ListExoRequest { param($Request, $TriggerMetadata) + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + try { $AllowedVerbs = @( 'Get' @@ -12,6 +16,7 @@ function Invoke-ListExoRequest { $Verb = ($Cmdlet -split '-')[0] $AllowedTenants = Test-CIPPAccess -Request $Request -TenantList + $TenantFilter = $Request.Body.TenantFilter $Tenants = Get-Tenants -IncludeErrors $Tenant = $Tenants | Where-Object { $_.defaultDomainName -eq $TenantFilter -or $_.customerId -eq $TenantFilter } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApplicationQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApplicationQueue.ps1 index 9fc4e3200ea5..a1109f79386a 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApplicationQueue.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApplicationQueue.ps1 @@ -11,11 +11,10 @@ Function Invoke-ListApplicationQueue { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' $Table = Get-CippTable -tablename 'apps' $QueuedApps = (Get-CIPPAzDataTableEntity @Table) @@ -24,7 +23,7 @@ Function Invoke-ListApplicationQueue { $ApplicationFile = $QueueFile.JSON | ConvertFrom-Json -Depth 10 [PSCustomObject]@{ tenantName = $ApplicationFile.tenant - applicationName = $ApplicationFile.Applicationname + applicationName = $ApplicationFile.applicationName cmdLine = $ApplicationFile.IntuneBody.installCommandLine assignTo = $ApplicationFile.assignTo id = $($QueueFile.RowKey) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListAppsRepository.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListAppsRepository.ps1 index 685d06eacf37..3048b6789138 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListAppsRepository.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListAppsRepository.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListAppsRepository { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' $Search = $Request.Body.Search $Repository = $Request.Body.Repository diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-RemoveApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-RemoveApp.ps1 index a58aa9f73140..3f9f1b3596f4 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-RemoveApp.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-RemoveApp.ps1 @@ -11,30 +11,31 @@ Function Invoke-RemoveApp { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $User = $Request.Headers - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $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. $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter $policyId = $Request.Query.ID ?? $Request.Body.ID + if (!$policyId) { exit } try { #$unAssignRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($policyId)')/assign" -type POST -Body '{"assignments":[]}' -tenant $TenantFilter $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/$($policyId)" -type DELETE -tenant $TenantFilter $Result = "Successfully deleted app with $policyId" - Write-LogMessage -Headers $User -API $APINAME -message $Result -Sev 'Info' -tenant $TenantFilter + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev Info -tenant $TenantFilter + $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - $Result = "Could not delete app with $policyId. Error: $($ErrorMessage.NormalizedError)" - Write-LogMessage -Headers $User -API $APINAME -message $Result -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - + $Result = "Failed to delete app with $policyId. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev Error -tenant $TenantFilter -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } - $Body = [pscustomobject]@{Results = "$Result" } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Body + StatusCode = $StatusCode + Body = @{'Results' = "$Result" } }) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAlertsQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAlertsQueue.ps1 index 460a36ad70a5..8d4436ef3412 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAlertsQueue.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAlertsQueue.ps1 @@ -11,11 +11,10 @@ Function Invoke-ListAlertsQueue { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' $WebhookTable = Get-CIPPTable -TableName 'WebhookRules' $WebhookRules = Get-CIPPAzDataTableEntity @WebhookTable diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAuditLogSearches.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAuditLogSearches.ps1 index 561384504174..4468443aece3 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAuditLogSearches.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAuditLogSearches.ps1 @@ -7,36 +7,48 @@ function Invoke-ListAuditLogSearches { #> Param($Request, $TriggerMetadata) - if ($Request.Query.TenantFilter) { - switch ($Request.Query.Type) { + + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + # Interact with the query parameters + $TenantFilter = $Request.Query.tenantFilter + $SearchId = $Request.Query.SearchId + $Days = $Request.Query.Days + $Type = $Request.Query.Type + + + if ($TenantFilter) { + switch ($Type) { 'Searches' { - $Results = Get-CippAuditLogSearches -TenantFilter $Request.Query.TenantFilter + $Results = Get-CippAuditLogSearches -TenantFilter $TenantFilter $Body = @{ Results = @($Results) Metadata = @{ - TenantFilter = $Request.Query.TenantFilter + TenantFilter = $TenantFilter TotalSearches = $Results.Count } } | ConvertTo-Json -Depth 10 -Compress } 'SearchResults' { try { - $Results = Get-CippAuditLogSearchResults -TenantFilter $Request.Query.TenantFilter -QueryId $Request.Query.SearchId + $Results = Get-CippAuditLogSearchResults -TenantFilter $TenantFilter -QueryId $SearchId } catch { $Results = @{ Error = $_.Exception.Message } } $Body = @{ Results = @($Results) Metadata = @{ - SearchId = $Request.Query.SearchId - TenantFilter = $Request.Query.TenantFilter + SearchId = $SearchId + TenantFilter = $TenantFilter TotalResults = $Results.Count } } | ConvertTo-Json -Depth 10 -Compress } default { - if ($Request.Query.Days) { - $Days = $Request.Query.Days + if ($Days) { + $Days = $Days } else { $Days = 1 } @@ -62,7 +74,7 @@ function Invoke-ListAuditLogSearches { Results = @($Results) Metadata = @{ StartTime = $StartTime - TenantFilter = $Request.Query.TenantFilter + TenantFilter = $TenantFilter } } | ConvertTo-Json -Depth 10 -Compress } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPAccessAssignments.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPAccessAssignments.ps1 index 83fae86a70ea..953e87831000 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPAccessAssignments.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPAccessAssignments.ps1 @@ -6,6 +6,10 @@ function Invoke-ListGDAPAccessAssignments { [CmdletBinding()] param($Request, $TriggerMetadata) + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $Id = $Request.Query.Id $TenantFilter = $env:TenantID diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericAllTenants.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericAllTenants.ps1 index f579777b5607..e8cdc66c8df8 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericAllTenants.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericAllTenants.ps1 @@ -10,6 +10,9 @@ Function Invoke-ListGenericAllTenants { [CmdletBinding()] param($Request, $TriggerMetadata) + + # XXX This feels like an unused endpoint to me. -Bobby + $TableURLName = ($QueueItem.tolower().split('?').Split('/') | Select-Object -First 1).toString() $QueueKey = (Invoke-ListCippQueue | Where-Object -Property Name -EQ $TableURLName | Select-Object -Last 1).RowKey Update-CippQueueEntry -RowKey $QueueKey -Status 'Started' diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericTestFunction.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericTestFunction.ps1 index cea9da93182e..bb2172b2ec95 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericTestFunction.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericTestFunction.ps1 @@ -11,8 +11,9 @@ Function Invoke-ListGenericTestFunction { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - $graphRequest = ($request.headers.'x-ms-original-url').split('/api') | Select-Object -First 1 + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $graphRequest = ($Headers.'x-ms-original-url').split('/api') | Select-Object -First 1 Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK From f3083481fe656971c8f703e029834159ebd76fc9 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 25 Feb 2025 18:57:40 -0500 Subject: [PATCH 074/167] feat: add ticket consolidation support --- .../Public/Halo/New-HaloPSATicket.ps1 | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/Modules/CippExtensions/Public/Halo/New-HaloPSATicket.ps1 b/Modules/CippExtensions/Public/Halo/New-HaloPSATicket.ps1 index 440e24842e1c..f1378374ee0d 100644 --- a/Modules/CippExtensions/Public/Halo/New-HaloPSATicket.ps1 +++ b/Modules/CippExtensions/Public/Halo/New-HaloPSATicket.ps1 @@ -8,8 +8,46 @@ function New-HaloPSATicket { #Get Halo PSA Token based on the config we have. $Table = Get-CIPPTable -TableName Extensionsconfig $Configuration = ((Get-CIPPAzDataTableEntity @Table).config | ConvertFrom-Json).HaloPSA - + $TicketTable = Get-CIPPTable -TableName 'PSATickets' $token = Get-HaloToken -configuration $Configuration + + if ($Configuration.ConsolidateTickets) { + $ExistingTicket = Get-CIPPAzDataTableEntity @TicketTable -Filter "PartitionKey eq 'HaloPSA' and RowKey eq '$($client)-$($title)'" + if ($ExistingTicket) { + Write-Information "Ticket already exists in HaloPSA: $($ExistingTicket.TicketID)" + + $Ticket = Invoke-RestMethod -Uri "$($Configuration.ResourceURL)/Tickets/$($ExistingTicket.TicketID)?includedetails=true&includelastaction=false&nocache=undefined&includeusersassets=false&isdetailscreen=true" -ContentType 'application/json; charset=utf-8' -Method Get -Headers @{Authorization = "Bearer $($token.access_token)" } + if (!$Ticket.hasbeenclosed) { + Write-Information 'Ticket is still open, adding new note' + $Object = [PSCustomObject]@{ + ticket_id = $ExistingTicket.TicketID + outcome = 'Private Note' + outcome_id = 7 + hiddenfromuser = $true + note_html = $description + } + $body = ConvertTo-Json -Compress -Depth 10 -InputObject @($Object) + try { + if ($PSCmdlet.ShouldProcess('Add note to HaloPSA ticket', 'Add note')) { + $Action = Invoke-RestMethod -Uri "$($Configuration.ResourceURL)/actions" -ContentType 'application/json; charset=utf-8' -Method Post -Body $body -Headers @{Authorization = "Bearer $($token.access_token)" } + Write-Information "Note added to ticket in HaloPSA: $($Action.id)" + } + return + } catch { + $Message = if ($_.ErrorDetails.Message) { + Get-NormalizedError -Message $_.ErrorDetails.Message + } else { + $_.Exception.message + } + Write-LogMessage -message "Failed to add note to HaloPSA ticket: $Message" -API 'HaloPSATicket' -sev Error -LogData (Get-CippException -Exception $_) + Write-Information "Failed to add note to HaloPSA ticket: $Message" + Write-Information "Body we tried to ship: $body" + return + } + } + } + } + $Object = [PSCustomObject]@{ files = $null usertype = 1 @@ -41,6 +79,16 @@ function New-HaloPSATicket { if ($PSCmdlet.ShouldProcess('Send ticket to HaloPSA', 'Create ticket')) { $Ticket = Invoke-RestMethod -Uri "$($Configuration.ResourceURL)/Tickets" -ContentType 'application/json; charset=utf-8' -Method Post -Body $body -Headers @{Authorization = "Bearer $($token.access_token)" } Write-Information "Ticket created in HaloPSA: $($Ticket.id)" + + if ($Configuration.ConsolidateTickets) { + $TicketObject = [PSCustomObject]@{ + PartitionKey = 'HaloPSA' + RowKey = "$($client)-$($title)" + TicketID = $Ticket.id + } + Add-CIPPAzDataTableEntity @TicketTable -Entity $TicketObject -Force + Write-Information 'Ticket added to consolidation table' + } } } catch { $Message = if ($_.ErrorDetails.Message) { From fbcd3c365d489b56d5d5244861125db0914b0828 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 25 Feb 2025 19:23:55 -0500 Subject: [PATCH 075/167] Update Push-ExecScheduledCommand.ps1 --- .../Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 index 4317db419974..abd5936d6f0d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 @@ -40,7 +40,7 @@ function Push-ExecScheduledCommand { Write-Host "Failed to remove parameters: $($_.Exception.Message)" } - $tenant = $Item.Parameters.TenantFilter + $tenant = $Item.Parameters.TenantFilter ?? $Item.Tenant Write-Host "Started Task: $($Item.Command) for tenant: $tenant" try { From 2e40de21575e03905765d9754c6f3086d4f67dfe Mon Sep 17 00:00:00 2001 From: Esco Date: Wed, 26 Feb 2025 11:55:02 +0100 Subject: [PATCH 076/167] feat: new UserPreferredLanguage standard --- ...voke-CIPPStandardUserPreferredLanguage.ps1 | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserPreferredLanguage.ps1 diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserPreferredLanguage.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserPreferredLanguage.ps1 new file mode 100644 index 000000000000..77784c0524bb --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserPreferredLanguage.ps1 @@ -0,0 +1,71 @@ +function Invoke-CIPPStandardUserPreferredLanguage { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) UserPreferredLanguage + .SYNOPSIS + (Label) Preferred language for all users + .DESCRIPTION + (Helptext) Sets the preferred language property for all users in the tenant. This will override the user's language settings. + (DocsDescription) Sets the preferred language property for all users in the tenant. This will override the user's language settings. + .NOTES + CAT + Entra (AAD) Standards + TAG + ADDEDCOMPONENT + {"type":"autoComplete","multiple":false,"creatable":false,"name":"standards.UserPreferredLanguage.preferredLanguage","label":"Preferred Language","api":{"url":"/languageList.json","labelField":"language","valueField":"tag"}} + IMPACT + High Impact + ADDEDDATE + 2025-02-26 + POWERSHELLEQUIVALENT + Update-MgUser -UserId user@domain.com -BodyParameter @{preferredLanguage='en-US'} + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/entra-aad-standards#high-impact + #> + + param($Tenant, $Settings) + + $preferredLanguage = $Settings.preferredLanguage.value + $IncorrectUsers = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`$top=999&`$select=userPrincipalName,displayName,preferredLanguage,userType,onPremisesSyncEnabled&`$filter=preferredLanguage ne '$preferredLanguage' and userType eq 'Member' and onPremisesSyncEnabled ne true&`$count=true&ConsistencyLevel=eventual" -tenantid $Tenant + + If ($Settings.remediate -eq $true) { + if (($IncorrectUsers | Measure-Object).Count -gt 0) { + try { + ForEach ($user in $IncorrectUsers) { + $cmdparams = @{ + tenantid = $Tenant + uri = "https://graph.microsoft.com/beta/users/$($user.userPrincipalName)" + AsApp = $true + Type = 'PATCH' + Body = @{ + preferredLanguage = $preferredLanguage + } | ConvertTo-Json + ContentType = 'application/json; charset=utf-8' + } + $null = New-GraphPOSTRequest @cmdparams + Write-LogMessage -API 'Standards' -tenant $tenant -message "Preferred language for $($user.userPrincipalName) has been set to $preferredLanguage" -sev Info + } + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to set preferred language to $preferredLanguage for all users." -sev Error -LogData $ErrorMessage + } + } + } + + If ($Settings.alert -eq $true) { + if (($IncorrectUsers.userPrincipalName | Measure-Object).Count -gt 0) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "The following accounts do not have the preferred language set to $preferredLanguage : $($IncorrectUsers.userPrincipalName -join ', ')" -sev Alert + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'No accounts do not have the preferred language set to the preferred language' -sev Info + } + } + + if ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'IncorrectUsers' -FieldValue $IncorrectUsers -StoreAs json -Tenant $tenant + } +} From 05165f0387b5e2b9a00580d1b2e74dec6201d4ec Mon Sep 17 00:00:00 2001 From: John Duprey Date: Wed, 26 Feb 2025 15:32:37 -0500 Subject: [PATCH 077/167] fix: azbobbytables issues convert data to psobject to avoid casing problem with hashtables update get function to use generic list and improve performance over something that looks suspiciously like += --- .../CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1 | 8 ++++++-- .../CIPPCore/Public/Get-CIPPAzDatatableEntity.ps1 | 14 +++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1 b/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1 index 4b4343a0296b..509be7e36fc2 100644 --- a/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1 +++ b/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1 @@ -137,14 +137,18 @@ function Add-CIPPAzDataTableEntity { foreach ($row in $rows) { Write-Information "current entity is $($row.RowKey) with $($row.PartitionKey). Our size is $([System.Text.Encoding]::UTF8.GetByteCount($($row | ConvertTo-Json -Compress)))" - Add-AzDataTableEntity -Context $Context -Force:$Force -CreateTableIfNotExists:$CreateTableIfNotExists -Entity $row + $NewRow = [PSCustomObject]$row + Add-AzDataTableEntity -Context $Context -Force:$Force -CreateTableIfNotExists:$CreateTableIfNotExists -Entity $NewRow } } else { - Add-AzDataTableEntity -Context $Context -Force:$Force -CreateTableIfNotExists:$CreateTableIfNotExists -Entity $SingleEnt + $NewEnt = [PSCustomObject]$SingleEnt + Add-AzDataTableEntity -Context $Context -Force:$Force -CreateTableIfNotExists:$CreateTableIfNotExists -Entity $NewEnt } } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-Warning ("AzBobbyTables Error") + Write-Information ($SingleEnt | ConvertTo-Json) throw "Error processing entity: $ErrorMessage Linenumber: $($_.InvocationInfo.ScriptLineNumber)" } } else { diff --git a/Modules/CIPPCore/Public/Get-CIPPAzDatatableEntity.ps1 b/Modules/CIPPCore/Public/Get-CIPPAzDatatableEntity.ps1 index f7f6362b8e22..27c4002fb814 100644 --- a/Modules/CIPPCore/Public/Get-CIPPAzDatatableEntity.ps1 +++ b/Modules/CIPPCore/Public/Get-CIPPAzDatatableEntity.ps1 @@ -23,10 +23,10 @@ function Get-CIPPAzDataTableEntity { } if (-not $mergedResults[$partitionKey].ContainsKey($entityId)) { $mergedResults[$partitionKey][$entityId] = @{ - Parts = New-Object 'System.Collections.ArrayList' + Parts = [System.Collections.Generic.List[object]]::new() } } - $mergedResults[$partitionKey][$entityId]['Parts'].Add($entity) > $null + $mergedResults[$partitionKey][$entityId]['Parts'].Add($entity) } else { $partitionKey = $entity.PartitionKey if (-not $mergedResults.ContainsKey($partitionKey)) { @@ -34,16 +34,16 @@ function Get-CIPPAzDataTableEntity { } $mergedResults[$partitionKey][$entity.RowKey] = @{ Entity = $entity - Parts = New-Object 'System.Collections.ArrayList' + Parts = [System.Collections.Generic.List[object]]::new() } } } - $finalResults = @() + $finalResults = [System.Collections.Generic.List[object]]::new() foreach ($partitionKey in $mergedResults.Keys) { foreach ($entityId in $mergedResults[$partitionKey].Keys) { $entityData = $mergedResults[$partitionKey][$entityId] - if ($entityData.Parts.Count -gt 0) { + if (($entityData.Parts | Measure-Object).Count -gt 0) { $fullEntity = [PSCustomObject]@{} $parts = $entityData.Parts | Sort-Object PartIndex foreach ($part in $parts) { @@ -60,9 +60,9 @@ function Get-CIPPAzDataTableEntity { $fullEntity | Add-Member -MemberType NoteProperty -Name 'PartitionKey' -Value $parts[0].PartitionKey -Force $fullEntity | Add-Member -MemberType NoteProperty -Name 'RowKey' -Value $entityId -Force $fullEntity | Add-Member -MemberType NoteProperty -Name 'Timestamp' -Value $parts[0].Timestamp -Force - $finalResults = $finalResults + @($fullEntity) + $finalResults.Add($fullEntity) } else { - $finalResults = $finalResults + @($entityData.Entity) + $FinalResults.Add($entityData.Entity) } } } From e82b27d664248de377ad4df8f3c857b85df967d3 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Wed, 26 Feb 2025 15:33:13 -0500 Subject: [PATCH 078/167] fix: improve graph request list performance update graph requests for all tenants / large queries to split data across properties/rows --- .../Push-ListGraphRequestQueue.ps1 | 29 +++++++++---------- .../GraphRequests/Get-GraphRequestList.ps1 | 16 +++++++--- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Graph Requests/Push-ListGraphRequestQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Graph Requests/Push-ListGraphRequestQueue.ps1 index 3c47e4eb5c51..a116159aba13 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Graph Requests/Push-ListGraphRequestQueue.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Graph Requests/Push-ListGraphRequestQueue.ps1 @@ -21,9 +21,9 @@ function Push-ListGraphRequestQueue { Write-Information "Queue Table: $TableName" $Table = Get-CIPPTable -TableName $TableName - $Filter = "PartitionKey eq '{0}' and Tenant eq '{1}'" -f $PartitionKey, $Item.TenantFilter + $Filter = "PartitionKey eq '{0}' and (RowKey eq '{1}' or OriginalEntityId eq '{1}')" -f $PartitionKey, $Item.TenantFilter Write-Information "Filter: $Filter" - $Existing = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey + $Existing = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey, OriginalEntityId if ($Existing) { $null = Remove-AzDataTableEntity -Force @Table -Entity $Existing } @@ -41,26 +41,25 @@ function Push-ListGraphRequestQueue { $RawGraphRequest = try { Get-GraphRequestList @GraphRequestParams } catch { + $CippException = Get-CippException -Exception $_.Exception [PSCustomObject]@{ Tenant = $Item.TenantFilter - CippStatus = "Could not connect to tenant. $($_.Exception.message)" + CippStatus = "Could not connect to tenant. $($CippException.NormalizedMessage)" + CippException = [string]($CippException | ConvertTo-Json -Depth 10 -Compress) } } - $GraphResults = foreach ($Request in $RawGraphRequest) { - $Json = ConvertTo-Json -Depth 10 -Compress -InputObject $Request - $RowKey = $Request.id ?? (New-Guid).Guid - [PSCustomObject]@{ - Tenant = [string]$Item.TenantFilter - QueueId = [string]$Item.QueueId - QueueType = [string]$Item.QueueType - RowKey = [string]$RowKey - PartitionKey = [string]$PartitionKey - Data = [string]$Json - } + $Json = ConvertTo-Json -Depth 10 -Compress -InputObject $RawGraphRequest + $GraphResults = [PSCustomObject]@{ + PartitionKey = [string]$PartitionKey + RowKey = [string]$Item.TenantFilter + QueueId = [string]$Item.QueueId + QueueType = [string]$Item.QueueType + Data = [string]$Json } Add-CIPPAzDataTableEntity @Table -Entity $GraphResults -Force | Out-Null } catch { - Write-Information "Queue Error: $($_.Exception.Message)" + Write-Warning "Queue Error: $($_.Exception.Message)" + #Write-Information ($GraphResults | ConvertTo-Json -Depth 10 -Compress) throw $_ } } diff --git a/Modules/CIPPCore/Public/GraphRequests/Get-GraphRequestList.ps1 b/Modules/CIPPCore/Public/GraphRequests/Get-GraphRequestList.ps1 index 98d09f7507c9..b66d9565e7fb 100644 --- a/Modules/CIPPCore/Public/GraphRequests/Get-GraphRequestList.ps1 +++ b/Modules/CIPPCore/Public/GraphRequests/Get-GraphRequestList.ps1 @@ -138,9 +138,9 @@ function Get-GraphRequestList { $Table = Get-CIPPTable -TableName $TableName $Timestamp = (Get-Date).AddHours(-1).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss.fffK') if ($TenantFilter -eq 'AllTenants') { - $Filter = "PartitionKey eq '{0}' and QueueType eq 'AllTenants' and Timestamp ge datetime'{1}'" -f $PartitionKey, $Timestamp + $Filter = "PartitionKey eq '{0}' and Timestamp ge datetime'{1}'" -f $PartitionKey, $Timestamp } else { - $Filter = "PartitionKey eq '{0}' and Tenant eq '{1}' and Timestamp ge datetime'{2}'" -f $PartitionKey, $TenantFilter, $Timestamp + $Filter = "PartitionKey eq '{0}' and (RowKey eq '{1}' or OriginalEntityId eq '{1}') and Timestamp ge datetime'{2}'" -f $PartitionKey, $TenantFilter, $Timestamp } $Rows = Get-CIPPAzDataTableEntity @Table -Filter $Filter $Type = 'Cache' @@ -337,8 +337,16 @@ function Get-GraphRequestList { } } } else { - $Rows | ForEach-Object { - $_.Data | ConvertFrom-Json + foreach ($Row in $Rows) { + if ($Row.Data) { + try { + $Row.Data | ConvertFrom-Json -ErrorAction Stop + } catch { + Write-Warning "Could not convert data to JSON: $($_.Exception.Message)" + #Write-Information ($Row | ConvertTo-Json) + continue + } + } } } } From 00617ff0690dd12ab554b8882bba798eaba07e9a Mon Sep 17 00:00:00 2001 From: John Duprey Date: Wed, 26 Feb 2025 17:52:25 -0500 Subject: [PATCH 079/167] update pwpush version --- .../Public/PwPush/Set-PwPushConfig.ps1 | 17 +- .../{1.2.1 => 1.3.1}/PSGetModuleInfo.xml | 0 .../{1.2.1 => 1.3.1}/PassPushPosh.psd1 | 4 +- .../{1.2.1 => 1.3.1}/PassPushPosh.psm1 | 496 +++++++++++------- 4 files changed, 328 insertions(+), 189 deletions(-) rename Modules/PassPushPosh/{1.2.1 => 1.3.1}/PSGetModuleInfo.xml (100%) rename Modules/PassPushPosh/{1.2.1 => 1.3.1}/PassPushPosh.psd1 (98%) rename Modules/PassPushPosh/{1.2.1 => 1.3.1}/PassPushPosh.psm1 (64%) diff --git a/Modules/CippExtensions/Public/PwPush/Set-PwPushConfig.ps1 b/Modules/CippExtensions/Public/PwPush/Set-PwPushConfig.ps1 index 6c816f6f5fc6..845b8e3caf49 100644 --- a/Modules/CippExtensions/Public/PwPush/Set-PwPushConfig.ps1 +++ b/Modules/CippExtensions/Public/PwPush/Set-PwPushConfig.ps1 @@ -19,21 +19,20 @@ function Set-PwPushConfig { } if (![string]::IsNullOrEmpty($Configuration.EmailAddress) -or $Configuration.UseBearerAuth -eq $true) { $ApiKey = Get-ExtensionAPIKey -Extension 'PWPush' - - if (![string]::IsNullOrEmpty($ApiKey)) { - $InitParams.APIKey = $ApiKey - } - if (![string]::IsNullOrEmpty($Configuration.EmailAddress)) { - $InitParams.EmailAddress = $Configuration.EmailAddress - } if ($Configuration.UseBearerAuth -eq $true) { - $InitParams.AccountType = 'Pro' + $InitParams.Bearer = $ApiKey + } elseif (![string]::IsNullOrEmpty($ApiKey)) { + if (![string]::IsNullOrEmpty($Configuration.EmailAddress)) { + $InitParams.EmailAddress = $Configuration.EmailAddress + } + $InitParams.APIKey = $ApiKey } } $Module = Get-Module PassPushPosh -ListAvailable - Write-Host $Module.Version + Write-Information "PWPush Version: $($Module.Version)" if ($PSCmdlet.ShouldProcess('Initialize-PassPushPosh')) { + Write-Information ($InitParams | ConvertTo-Json) Initialize-PassPushPosh @InitParams } } diff --git a/Modules/PassPushPosh/1.2.1/PSGetModuleInfo.xml b/Modules/PassPushPosh/1.3.1/PSGetModuleInfo.xml similarity index 100% rename from Modules/PassPushPosh/1.2.1/PSGetModuleInfo.xml rename to Modules/PassPushPosh/1.3.1/PSGetModuleInfo.xml diff --git a/Modules/PassPushPosh/1.2.1/PassPushPosh.psd1 b/Modules/PassPushPosh/1.3.1/PassPushPosh.psd1 similarity index 98% rename from Modules/PassPushPosh/1.2.1/PassPushPosh.psd1 rename to Modules/PassPushPosh/1.3.1/PassPushPosh.psd1 index 0e676121021f..3061f5864953 100644 --- a/Modules/PassPushPosh/1.2.1/PassPushPosh.psd1 +++ b/Modules/PassPushPosh/1.3.1/PassPushPosh.psd1 @@ -3,7 +3,7 @@ # # Generated by: Adam Burley # -# Generated on: 2/8/2025 +# Generated on: 2/21/2025 # @{ @@ -12,7 +12,7 @@ RootModule = 'PassPushPosh.psm1' # Version number of this module. -ModuleVersion = '1.2.1' +ModuleVersion = '1.3.1' # Supported PSEditions CompatiblePSEditions = 'Core' diff --git a/Modules/PassPushPosh/1.2.1/PassPushPosh.psm1 b/Modules/PassPushPosh/1.3.1/PassPushPosh.psm1 similarity index 64% rename from Modules/PassPushPosh/1.2.1/PassPushPosh.psm1 rename to Modules/PassPushPosh/1.3.1/PassPushPosh.psm1 index e4d7643eec11..35acb630d634 100644 --- a/Modules/PassPushPosh/1.2.1/PassPushPosh.psm1 +++ b/Modules/PassPushPosh/1.3.1/PassPushPosh.psm1 @@ -3,8 +3,6 @@ class PasswordPush { [string]$Note [string]$Payload - [string] hidden $__UrlToken - [string] hidden $__LinkBase [bool]$RetrievalStep [bool]$IsExpired [bool]$IsDeleted @@ -16,11 +14,12 @@ class PasswordPush { [DateTime]$DateCreated [DateTime]$DateUpdated [DateTime]$DateExpired - # Added by constructors: - #[string]$URLToken - #[string]$Link - #[string]$LinkDirect - #[string]$LinkRetrievalStep + [int]$AccountId + [string]$UrlToken + [string]$Link + [string]$LinkDirect + [string]$LinkRetrievalStep + #[PSCustomObject[]]$Files # Added if present PasswordPush() { # Blank constructor @@ -28,16 +27,7 @@ class PasswordPush { # Constructor to allow casting or explicit import from a PSObject Representing the result of an API call PasswordPush([PSCustomObject]$APIresponseObject) { - throw NotImplementedException - } - - # Allow casting or explicit import from the raw Content of an API call - [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', '', Scope = 'Function', Justification = 'Global variables are used for module session helpers.')] - PasswordPush([string]$JsonResponse) { - Write-Debug 'New PasswordPush object instantiated from JsonResponse string' - Initialize-PassPushPosh # Initialize the module if not yet done. - - $_j = $JsonResponse | ConvertFrom-Json + $_j = $APIresponseObject $this.Note = $_j.note $this.Payload = $_j.payload $this.IsExpired = $_j.expired @@ -51,35 +41,18 @@ class PasswordPush { $this.DateUpdated = $_j.updated_at $this.DateExpired = if ($_j.expired_on) { $_j.expired_on } else { [DateTime]0 } $this.RetrievalStep = $_j.retrieval_step - - - $this | Add-Member -Name 'UrlToken' -MemberType ScriptProperty -Value { - return $this.__UrlToken - } -SecondValue { - $this.__UrlToken = $_ - $this.__LinkBase = $_j.html_url ?? "$Script:PPPBaseUrl/p/$($this.__UrlToken)" - } - $this.__UrlToken = $_j.url_token - $this.__LinkBase = $_j.html_url ?? "$Script:PPPBaseUrl/p/$($this.__UrlToken)" - $this | Add-Member -Name 'LinkDirect' -MemberType ScriptProperty -Value { return $this.__LinkBase } -SecondValue { - Write-Warning 'LinkDirect is a read-only calculated member.' - Write-Debug 'Link* members are calculated based on the Global BaseUrl and Push Retrieval Step values' - } - $this | Add-Member -Name 'LinkRetrievalStep' -MemberType ScriptProperty -Value { return "$($this.__LinkBase)/r" } -SecondValue { - Write-Warning 'LinkRetrievalStep is a read-only calculated member.' - Write-Debug 'Link* members are calculated based on the Global BaseUrl and Push Retrieval Step values' - } - $this | Add-Member -Name 'Link' -MemberType ScriptProperty -Value { - $_Link = if ($this.RetrievalStep) { $this.LinkRetrievalStep } else { $this.LinkDirect } - Write-Debug "Presented Link: $_link" - $_Link - } -SecondValue { - Write-Warning 'Link is a read-only calculated member.' - Write-Debug 'Link* members are calculated based on the Global BaseUrl and Push Retrieval Step values' + $this.AccountId = $_j.account_id + $this.UrlToken = $_j.url_token + $this.LinkDirect = $_j.json_url ? $_j.json_url.Replace('.json','') : "$Script:PPPBaseUrl/p/$($this.UrlToken)" + $this.LinkRetrievalStep = $this.LinkDirect, '/r' -join '' + $this.Link = $_j.html_url ?? $this.RetrievalStep -eq $true ? $this.LinkRetrievalStep : $this.LinkDirect + + if ($_j.Files) { + $this | Add-Member -MemberType NoteProperty -Name Files -Value $_j.files } } } -#EndRegion '.\Classes\PasswordPush.ps1' 80 +#EndRegion '.\Classes\PasswordPush.ps1' 53 #Region '.\Classes\TypeAccelerators.ps1' -1 # https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_classes?view=powershell-7.4#exporting-classes-with-type-accelerators @@ -189,13 +162,12 @@ function ConvertTo-PasswordPush { param( [parameter(Mandatory, ValueFromPipeline)] [ValidateNotNullOrEmpty()] - $JsonResponse + [PSCustomObject]$JsonResponse ) process { try { - $jsonObject = if ($JsonResponse -is [string]) { $JsonResponse | ConvertFrom-Json } else { $JsonResponse } - foreach ($o in $jsonObject) { - [PasswordPush]($o | ConvertTo-Json) # TODO fix this mess + foreach ($o in $JsonResponse) { + [PasswordPush]::New($o) } } catch { @@ -205,7 +177,7 @@ function ConvertTo-PasswordPush { } } } -#EndRegion '.\Private\ConvertTo-PasswordPush.ps1' 84 +#EndRegion '.\Private\ConvertTo-PasswordPush.ps1' 83 #Region '.\Private\Format-PasswordPusherSecret.ps1' -1 function Format-PasswordPusherSecret { @@ -238,13 +210,18 @@ function Format-PasswordPusherSecret { #Region '.\Private\Invoke-PasswordPusherAPI.ps1' -1 function Invoke-PasswordPusherAPI { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'Body')] [OutputType([PSCustomObject])] param( [string]$Endpoint, [Microsoft.PowerShell.Commands.WebRequestMethod]$Method = [Microsoft.PowerShell.Commands.WebRequestMethod]::Get, + + [Parameter(ParameterSetName = 'Body')] [object]$Body, + [Parameter(ParameterSetName = 'Form')] + [object]$Form, + [Switch]$ReturnErrors ) process { @@ -253,18 +230,22 @@ function Invoke-PasswordPusherAPI { $iwrSplat = @{ 'Method' = $Method - 'ContentType' = 'application/json' - 'Body' = ($body | ConvertTo-Json) 'Uri' = $_uri 'UserAgent' = $Script:PPPUserAgent } + if ($PSCmdlet.ParameterSetName -eq 'Form') { + $iwrSplat.Form = $Form + } else { + $iwrSplat.Body = ($body | ConvertTo-Json) + $iwrSplat.ContentType = 'application/json' + } if ($Script:PPPHeaders.'X-User-Token') { $iwrSplat['Headers'] = $Script:PPPHeaders - Write-Debug "Authenticated with API token $(Format-PasswordPusherSecret -Secret $Script:PPPHeaders.'X-User-Token' -ShowSample)" + Write-Debug "Authenticated with X-User-Token $(Format-PasswordPusherSecret -Secret $Script:PPPHeaders.'X-User-Token' -ShowSample)" } if ($Script:PPPHeaders.'Authorization') { $iwrSplat['Headers'] = $Script:PPPHeaders - Write-Debug "Authenticated with API token $(Format-PasswordPusherSecret -Secret $Script:PPPHeaders.'Authorization' -ShowSample)" + Write-Debug "Authenticated with Bearer token $(Format-PasswordPusherSecret -Secret $Script:PPPHeaders.'Authorization' -ShowSample)" } $callInfo = "$Method $_uri" Write-Verbose "Sending HTTP request: $callInfo" @@ -283,7 +264,23 @@ function Invoke-PasswordPusherAPI { } } } -#EndRegion '.\Private\Invoke-PasswordPusherAPI.ps1' 47 +#EndRegion '.\Private\Invoke-PasswordPusherAPI.ps1' 56 +#Region '.\Private\New-PasswordPusherUserAgent.ps1' -1 + +function New-PasswordPusherUserAgent { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Scope = 'Function', Justification = 'Function does not change state.')] + [CmdletBinding()] + [OutputType([string])] + param() + $osVersion = [System.Environment]::OSVersion + $userAtDomain = '{0}@{1}' -f [System.Environment]::UserName, [System.Environment]::UserDomainName + $uAD64 = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($userAtDomain)) + Write-Debug "$userAtDomain transformed to $uAD64. First 20 characters $($uAD64.Substring(0,20))" + + # Version tag is replaced by the semantic version number at build time. See PassPushPosh/issues/11 for context + "PassPushPosh/1.3.1 $osVersion/$($uAD64.Substring(0,20))" +} +#EndRegion '.\Private\New-PasswordPusherUserAgent.ps1' 14 #Region '.\Public\Get-Dashboard.ps1' -1 <# @@ -354,6 +351,14 @@ function Get-Dashboard { .PARAMETER Passhrase An additional phrase required to view the secret. Required if the Push was created with a Passphrase. + .PARAMETER OutFolder + For File pushes, a folder path to save files. If the folder path does not exist + it will be created. Files are saved with their original names. + + .PARAMETER IncludePushObject + When saving files from a file push, also save the push data itself. This will + create a JSON object in the same path as the files with the + .INPUTS [string] @@ -369,19 +374,13 @@ function Get-Dashboard { .LINK https://github.com/adamburley/PassPushPosh/blob/main/Docs/Get-Push.md - .LINK - https://pwpush.com/api/1.0/passwords.en.html - - .LINK - https://github.com/pglombardo/PasswordPusher/blob/c2909b2d5f1315f9b66939c9fbc7fd47b0cfeb03/app/controllers/passwords_controller.rb#L89 - .LINK New-Push #> function Get-Push { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "Passphrase", Justification = "DE0001: SecureString shouldn't be used")] - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'Text')] [OutputType([PasswordPush])] param( [Parameter(Mandatory, ValueFromPipeline)] @@ -390,20 +389,50 @@ function Get-Push { $URLToken, [Parameter()] - [String]$Passphrase + [String]$Passphrase, + + [Parameter(ParameterSetName = 'Out File')] + [Alias('OutFile')] + [System.IO.DirectoryInfo]$OutFolder, + + [Parameter(ParameterSetName = 'Out File')] + [switch]$IncludePushObject ) begin { Initialize-PassPushPosh -Verbose:$VerbosePreference -Debug:$DebugPreference } process { $endpoint = $Passphrase ? "p/$URLToken.json?passphrase=$Passphrase" : "p/$URLToken.json" $result = Invoke-PasswordPusherAPI -Endpoint $endpoint -ReturnErrors - switch ($result.error){ - 'not-found' { Write-Error -Message "Push not found. Check the token you provided. Tokens are case-sensitive." } - 'This push has a passphrase that was incorrect or not provided.' { if ($Passphrase) { Write-Error -Message "Incorrect passphrase provided." } else { Write-Error -Message "Passphrase required. Specify with the -Passphrase parameter." } } - default { $result | ConvertTo-PasswordPush } + if ($result.error){ + if ($result.error -eq 'not-found') { Write-Error -Message "Push not found. Check the token you provided. Tokens are case-sensitive." } + if ($result.error -eq 'This push has a passphrase that was incorrect or not provided.') { if ($Passphrase) { Write-Error -Message "Incorrect passphrase provided." } else { Write-Error -Message "Passphrase required. Specify with the -Passphrase parameter." } } + } + $pushObject = $result | ConvertTo-PasswordPush + if ($OutFolder) { + if ($pushObject.Files.Count -gt 0) { + if (-not (Test-Path -Path $OutFolder -PathType Container)) { + New-Item -Path $OutFolder -ItemType Directory | Out-Null + Write-Verbose "$OutFolder does not exist and was created." + } else { + Write-Verbose "Saving files to $OutFolder" + } + foreach ($f in $pushObject.Files){ + Write-Verbose "Saving $($f.filename) [$($f.content_type)]" + Invoke-WebRequest -Uri $f.url -OutFile (Join-Path -Path $OutFolder -ChildPath $f.filename) + } + if ($IncludePushObject) { + $pushObject | ConvertTo-Json -Depth 10 | Out-File (Join-Path $OutFolder -ChildPath "Push_$($pushObject.UrlToken).json") + } + } else { + Write-Warning "No files were included in this push. Nothing was saved." + } + $pushObject + } + else { + $pushObject } } } -#EndRegion '.\Public\Get-Push.ps1' 65 +#EndRegion '.\Public\Get-Push.ps1' 97 #Region '.\Public\Get-PushAccount.ps1' -1 <# @@ -585,17 +614,27 @@ function Get-SecretLink { This function is called automatically if needed, defaulting to the public pwpush.com service. - .PARAMETER AccountType - For paid users, specify the account type as Premium or Pro. Not required for free accounts and self-hosted. + .PARAMETER Bearer + API key for authenticated calls. Supported on hosted instance and OSS v1.51.0 and newer. + + .PARAMETER ApiKey + API key for authenticated calls. Supports older OSS installs. + Also supports Bearer autodetection. This will be removed in a future version. .PARAMETER EmailAddress Email address for authenticated calls. + NOTE: This is only required for legacy X-User-Token authentication. If using hosted pwpush.com + services or OSS v1.51.0 or newer use -Bearer - .PARAMETER ApiKey - API key for authenticated calls. + .PARAMETER UseLegacyAuth + Use legacy X-User-Token. Supportsversions of Password Pusher OSS older than v1.51.0. + If this is not set, but -ApiKey and -EmailAddress are specified the module will attempt to + auto-detect the correct connection. .PARAMETER BaseUrl - Base URL for API calls. Allows use of module with private instances of Password Pusher + Base URL for API calls. Allows use of custom domains with hosted Password Pusher as well as specifying + a private instance. + Default: https://pwpush.com .PARAMETER UserAgent @@ -608,23 +647,23 @@ function Get-SecretLink { .PARAMETER Force Force setting new information. If module is already initialized you can use this to - Re-initialize with default settings. Implied if either ApiKey or BaseUrl is provided. + re-initialize the module. If not specified and there is an existing session the request is ignored. .EXAMPLE - # Initialize with default settings + # Default settings PS > Initialize-PassPushPosh .EXAMPLE - # Initialize with authentication - PS > Initialize-PassPushPosh -EmailAddress 'youremail@example.com' -ApiKey '239jf0jsdflskdjf' -Verbose - - VERBOSE: Initializing PassPushPosh. ApiKey: [x-kdjf], BaseUrl: https://pwpush.com + # Authentication + PS > Initialize-PassPushPosh -Bearer 'myreallylongapikey' .EXAMPLE - # Initialize with another server with authentication - PS > Initialize-PassPushPosh -BaseUrl https://myprivatepwpushinstance.com -EmailAddress 'youremail@example.com' -ApiKey '239jf0jsdflskdjf' -Verbose + # Initialize with another domain - may be a private instance or a hosted instance with custom domain + PS > Initialize-PassPushPosh -BaseUrl https://myprivatepwpushinstance.example.com -Bearer 'myreallylongapikey' - VERBOSE: Initializing PassPushPosh. ApiKey: [x-kdjf], BaseUrl: https://myprivatepwpushinstance.com + .EXAMPLE + # Legacy authentication support + PS > Initialize-PassPushPosh -ApiKey 'myreallylongapikey' -EmailAddress 'myregisteredemail@example.com' -UseLegacyAuthentication -BaseUrl https://myprivatepwpushinstance.example.com .EXAMPLE # Set a custom User Agent @@ -634,29 +673,30 @@ function Get-SecretLink { https://github.com/adamburley/PassPushPosh/blob/main/Docs/Initialize-PassPushPosh.md .NOTES - -WhatIf setting for Set-Variable -Script is disabled, otherwise -WhatIf - calls for other functions would return incorrect data in the case this - function has not yet run. + The use of X-USER-TOKEN for authentication is depreciated and will be removed in a future release of the API. + This module will support it via legacy mode, initially by attempting to auto-detect if Bearer is supported. + New code using this module should use -Bearer (most cases) or -UseLegacyAuthentication (self-hosted older versions). + In a future release the module will default to Bearer unless the -UseLegacyAuthentication switch is set. + #> function Initialize-PassPushPosh { [CmdletBinding(DefaultParameterSetName = 'Anonymous')] param ( - [Parameter(ParameterSetName = 'Pro')] - [ValidateSet('Premium', 'Pro')] - [string]$AccountType = 'Pro', + [Parameter(ParameterSetName = 'Authenticated')] + [string]$Bearer, - [Parameter(Mandatory, Position = 0, ParameterSetName = 'Authenticated')] + [Parameter(Mandatory, Position = 0, ParameterSetName = 'Legacy Auth')] + [ValidateLength(5, 256)] + [string]$ApiKey, + + [Parameter(Mandatory, Position = 1, ParameterSetName = 'Legacy Auth')] [ValidatePattern('.+\@.+\..+', ErrorMessage = 'Please specify a valid email address')] [string]$EmailAddress, - [Parameter(Mandatory, ParameterSetName = 'Pro')] - [Parameter(Mandatory, Position = 1, ParameterSetName = 'Authenticated')] - [ValidateLength(5, 256)] - [string]$ApiKey, + [Parameter(ParameterSetName = 'Legacy Auth')] + [switch]$UseLegacyAuthentication, - [Parameter(Position = 0, ParameterSetName = 'Anonymous')] - [Parameter(Position = 2, ParameterSetName = 'Authenticated')] - [Parameter(ParameterSetName = 'Pro')] + [Parameter()] [ValidatePattern('^https?:\/\/[a-zA-Z0-9-_]+.[a-zA-Z0-9]+')] [string]$BaseUrl, @@ -665,60 +705,65 @@ function Initialize-PassPushPosh { [string] $UserAgent, - [Parameter()][switch]$Force + [Parameter()] + [switch]$Force ) - if ($Script:PPPBaseURL -and $true -inotin $Force, [bool]$ApiKey, [bool]$BaseUrl, [bool]$UserAgent) { Write-Debug -Message 'PassPushPosh is already initialized.' } + if ($Script:PPPBaseURL -and -not $Force) { Write-Debug -Message 'PassPushPosh is already initialized.' } else { - $defaultBaseUrl = 'https://pwpush.com' - $apiKeyOutput = $ApiKey ? (Format-PasswordPusherSecret -Secret $ApiKey -ShowSample) : 'None' + $_baseUrl = $PSBoundParameters.ContainsKey('BaseUrl') ? $BaseUrl : 'https://pwpush.com' + $_apiKey = $PSBoundParameters.ContainsKey('Bearer') ? $Bearer : $ApiKey - if (-not $Script:PPPBaseURL) { - # Not initialized - if (-not $BaseUrl) { $BaseUrl = $defaultBaseUrl } - Write-Verbose "Initializing PassPushPosh. ApiKey: [$apiKeyOutput], BaseUrl: $BaseUrl" - } - elseif ($Force -or $ApiKey -or $BaseURL) { - if (-not $BaseUrl) { $BaseUrl = $defaultBaseUrl } - $oldApiKeyOutput = if ($Script:PPPApiKey) { Format-PasswordPusherSecret -Secret $Script:PPPApiKey -ShowSample } else { 'None' } - Write-Verbose "Re-initializing PassPushPosh. Old ApiKey: [$oldApiKeyOutput] New ApiKey: [$apiKeyOutput], Old BaseUrl: $Script:PPPBaseUrl New BaseUrl: $BaseUrl" - } - if ($PSCmdlet.ParameterSetName -eq 'Authenticated') { + $apiKeySample = $_apiKey ? (Format-PasswordPusherSecret -Secret $_apiKey -ShowSample) : 'None' - Set-Variable -Scope Script -Name PPPHeaders -WhatIf:$false -Value @{ - 'X-User-Email' = $EmailAddress - 'X-User-Token' = $ApiKey + $_AuthType = $PSCmdlet.ParameterSetName -iin 'Anonymous', 'Authenticated' ? $PSCmdlet.ParameterSetName : $UseLegacyAuthentication ? 'Legacy' : 'Automatic' + + switch ($_AuthType) { + 'Anonymous' { + # module is reinitialized from an authenticated to an anonymous session + Remove-Variable -Scope Script -Name PPPHeaders -WhatIf:$false -ErrorAction SilentlyContinue } - } - elseif ($PSCmdlet.ParameterSetName -eq 'Pro') { - Write-Debug "Initializing for paid tier $($AccountType)" - Set-Variable -Scope Script -Name PPPHeaders -WhatIf:$false -Value @{ - 'Authorization' = "Bearer $ApiKey" + 'Authenticated' { + Write-Debug 'Bearer auth specified.' + Set-Variable -Scope Script -Name PPPHeaders -WhatIf:$false -Value @{ + 'Authorization' = "Bearer $_apiKey" + } + } + 'Legacy' { + Write-Debug 'Legacy auth specified.' + Set-Variable -Scope Script -Name PPPHeaders -WhatIf:$false -Value @{ + 'X-User-Email' = $EmailAddress + 'X-User-Token' = $_apiKey + } + } + 'Automatic' { + Write-Debug 'Legacy auth status not specified Checking for /up' + if ((Invoke-WebRequest "$_baseUrl/up" -SkipHttpErrorCheck).StatusCode -eq 200) { + Write-Debug "Current version detected via /up" + Set-Variable -Scope Script -Name PPPHeaders -WhatIf:$false -Value @{ + 'Authorization' = "Bearer $_apiKey" + } + } else { + Write-Warning 'Instance does not appear to support modern Bearer authentication.' + Write-Warning 'The module will fall back to using legacy authentication.' + Write-Warning 'If you are connecting to a self-hosted instance, verify it is up to date.' + Write-Warning 'If you know you need legacy (X-User-Token) authentication include Invoke-PassPushPosh -UseLegacyAuth $true' + Write-Warning 'To skip the step check and this warning.' + Set-Variable -Scope Script -Name PPPHeaders -WhatIf:$false -Force -Value @{ + 'X-User-Email' = $EmailAddress + 'X-User-Token' = $_apiKey + } + } } - } - elseif ($Script:PPPHeaders) { - # Remove if present - covers case where module is reinitialized from an authenticated to an anonymous session - Remove-Variable -Scope Script -Name PPPHeaders -WhatIf:$false } - if (-not $UserAgent) { - $osVersion = [System.Environment]::OSVersion - $userAtDomain = '{0}@{1}' -f [System.Environment]::UserName, [System.Environment]::UserDomainName - $uAD64 = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($userAtDomain)) - Write-Debug "$userAtDomain transformed to $uAD64. First 20 characters $($uAD64.Substring(0,20))" - # Version tag is replaced by the semantic version number at build time. See PassPushPosh/issues/11 for context - $UserAgent = "PassPushPosh/1.2.1 $osVersion/$($uAD64.Substring(0,20))" - # $UserAgent = "PassPushPosh/$((Get-Module -Name PassPushPosh).Version.ToString()) $osVersion/$($uAD64.Substring(0,20))" - Write-Verbose "Generated user agent: $UserAgent" - } - else { - Write-Verbose "Using specified user agent: $UserAgent" - } + Set-Variable -WhatIf:$false -Scope Script -Name PPPUserAgent -Value ($PSBoundParameters.ContainsKey('UserAgent') ? $UserAgent : (New-PasswordPusherUserAgent)) + Set-Variable -WhatIf:$false -Scope Script -Name PPPBaseURL -Value $_baseUrl.TrimEnd('/') - Set-Variable -WhatIf:$false -Scope Script -Name PPPBaseURL -Value $BaseUrl.TrimEnd('/') - Set-Variable -WhatIf:$false -Scope Script -Name PPPUserAgent -Value $UserAgent + Write-Verbose -Message "PassPushPosh Initialized with these settings: Account type: [$_AuthType] API Key: $apiKeySample Base URL: [$_baseUrl]" + Write-Verbose -Message "User Agent: $Script:PPPUserAgent" } } -#EndRegion '.\Public\Initialize-PassPushPosh.ps1' 146 +#EndRegion '.\Public\Initialize-PassPushPosh.ps1' 162 #Region '.\Public\New-Push.ps1' -1 <# @@ -733,13 +778,31 @@ function Initialize-PassPushPosh { are always provided at LinkRetrievalStep and LinkDirect properties. .PARAMETER Payload - The URL password or secret text to share. + Generic text value to share. Use with -Kind to create arbitrary push types. + Payload is required for all types except File. For QR and URL pushes you + may directly specify those types by using the -QR and -URL parameters. + + .PARAMETER QR + Create a QR-type secret with this text value. May be a link or other text. + + .PARAMETER URL + Create a URL-type secret redirecting to this link. A fully-qualified URL is + required + + .PARAMETER File + Attach files to a push. Up to 10 files in all referenced folders and paths + may be specified by passing a file or folder path or array of paths or a + DirectoryInfo or FileInfo object. + + File pushes can be files only, files with text, or files with a QR code. + To add text, simply use -Payload. To specify a QR code, use -QR or use + -Payload 'your value' -Type QR .PARAMETER Passphrase Require recipients to enter this passphrase to view the created push. .PARAMETER Note - The note for this push. Visible only to the push creator. Requires authentication. + The note for this push. Visible only to the push creator. Requires authentication. .PARAMETER ExpireAfterDays Expire secret link and delete after this many days. @@ -759,6 +822,15 @@ function Initialize-PassPushPosh { .PARAMETER AccountId Account ID to associate with this push. Requires authentication. + If you have multiple accounts and you do not specify an account ID + Password Pusher will use the first account available, UNLESS you have a custom domain. + In that case it will default to the custom domain account IF you're connecting + to the custom domain for the API session. If you're connecting to pwpush.com, + it will use the unbranded / non-domain account. + + .PARAMETER Kind + The kind of Push to send. Defaults to text. If using -QR, -URL, or -File parameters + the correct kind is automatically selected and this parameter is ignored. .INPUTS [string] @@ -784,14 +856,30 @@ function Initialize-PassPushPosh { # "Burn after reading" style Push PS > New-Push -Payload "Still secret text!" -ExpireAfterViews 1 -RetrievalStep - .LINK - https://github.com/adamburley/PassPushPosh/blob/main/Docs/New-Push.md + .EXAMPLE + Create a URL push + PS > New-Push -URL 'https://example.com/coolplacetoforwardmyrecipientto' + + .EXAMPLE + Create a QR push + PS > New-Push -QR 'thing i want to show up when someone reads the QR code' + + .EXAMPLE + Create a file push + PS > New-Push -File 'C:\mytwofiles\mycoolfile.txt', 'C:\mytwofiles\mycoolfile2.txt' + or + PS > New-Push -File 'C:\mytwofiles' + or + PS > $myFolder = Get-ChildItem C:\mytwofiles + PS > New-Push -File $myFolder + + .EXAMPLE + Create a QR push using -Payload + PS > New-Push -Payload 'this is my qr code value' -Kind QR - .LINK - https://pwpush.com/api/1.0/passwords/create.en.html .LINK - https://github.com/pglombardo/PasswordPusher/blob/c2909b2d5f1315f9b66939c9fbc7fd47b0cfeb03/app/controllers/passwords_controller.rb#L120 + https://github.com/adamburley/PassPushPosh/blob/main/Docs/New-Push.md .LINK Get-Push @@ -799,23 +887,35 @@ function Initialize-PassPushPosh { .NOTES Maximum for -ExpireAfterDays and -ExpireAfterViews is based on the default values for Password Pusher and what's used on the public instance - (pwpush.com). If you're using this with a private instance and want to - override that value you'll need to fork this module. + (pwpush.com). #> function New-Push { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', 'Passphrase', Justification = "DE0001: SecureString shouldn't be used")] - [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Low', DefaultParameterSetName = 'Anonymous')] + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Low', DefaultParameterSetName = 'Text')] [OutputType([PasswordPush])] param( - [Parameter(Mandatory = $true, ValueFromPipeline, Position = 0)] + [Parameter(ParameterSetName = 'Text', ValueFromPipeline, Position = 0)] [Alias('Password')] [ValidateNotNullOrEmpty()] [string]$Payload, + [Parameter(ParameterSetName = 'QR', Mandatory)] + [string]$QR, + + [Parameter(ParameterSetName = 'URL', Mandatory)] + [ValidatePattern('^https?:\/\/[a-zA-Z0-9-_]+.[a-zA-Z0-9]+')] + [string]$URL, + + [Parameter(ParameterSetName = 'Text')] + [Parameter(ParameterSetName = 'QR')] + [ValidateCount(1, 10)] + [ValidateScript({ $null -ne $Script:PPPHeaders.'X-User-Token' -or $null -ne $Script:PPPHeaders.Authorization }, ErrorMessage = 'Adding files requires authentication.')] + [object[]]$File, + [Parameter()] [string]$Passphrase, - [Parameter(ParameterSetName = 'Authenticated')] + [Parameter()] [ValidateScript({ $null -ne $Script:PPPHeaders.'X-User-Token' -or $null -ne $Script:PPPHeaders.Authorization }, ErrorMessage = 'Adding a note requires authentication.')] [ValidateNotNullOrEmpty()] [string]$Note, @@ -840,60 +940,100 @@ function New-Push { [Parameter()] [ValidateScript({ $null -ne $Script:PPPHeaders.Authorization }, ErrorMessage = 'Adding an account id requires authentication.')] - $AccountId + $AccountId, + + [Parameter(ParameterSetName = 'Text')] + [ValidateSet('Text', 'File', 'QR', 'URL')] + [string]$Kind = 'Text' ) begin { Initialize-PassPushPosh -Verbose:$VerbosePreference -Debug:$DebugPreference } process { - $body = @{ - 'password' = @{ - 'payload' = $Payload + $_Kind = switch ($PSCmdlet.ParameterSetName) { + 'QR' { 'qr' } + 'URL' { 'url' } + default { + $File ? 'file' : $Kind.ToLower() } } - $shouldString = 'Submit {0} push with Payload of length {1}' -f $PSCmdlet.ParameterSetName, $Payload.Length + Write-Debug "Parameter Set: $($PSCmdlet.ParameterSetName)" + Write-Debug "Kind: $_Kind" + + $passVals = @{ 'kind' = $_Kind } + $shouldString = "Submit $_Kind push" + + if ($_Payload = $Payload ? $Payload : $QR ? $QR : $URL ? $URL : $Null) { + $shouldString += ", with payload of length $($_Payload.Length)" + $passVals.payload = $_Payload + } + elseif ($_Kind -ine 'File') { + Write-Error "A payload is required for all Push types except File." -ErrorAction Stop + } if ($Passphrase) { - $body.password.passphrase = $Passphrase + $passVals.passphrase = $Passphrase $shouldString += ", with passphrase of length $($Passphrase.Length)" } if ($Note) { - $body.password.note = $note + $passVals.note = $note $shouldString += ", with note $note" } if ($ExpireAfterDays) { - $body.password.expire_after_days = $ExpireAfterDays - $shouldString += ', expire after {0} days' -f $ExpireAfterDays + $passVals.expire_after_days = $ExpireAfterDays + $shouldString += ", expire after $ExpireAfterDays days" } if ($ExpireAfterViews) { - $body.password.expire_after_views = $ExpireAfterViews - $shouldString += ', expire after {0} views' -f $ExpireAfterViews + $passVals.expire_after_views = $ExpireAfterViews + $shouldString += ", expire after $ExpireAfterViews views" } - if ($AccountId) { - $body.account_id = $AccountId - $shouldString += ', with account ID {0}' -f $AccountId + if ($PSBoundParameters.ContainsKey('DeletableByViewer')) { + $passVals.deletable_by_viewer = [bool]$DeletableByViewer + $shouldString += $DeletableByViewer ? ', deletable by viewer' : ', not deletable by viewer' } - $body.password.deletable_by_viewer = if ($DeletableByViewer) { - $shouldString += ', deletable by viewer' - $true - } else { - $shouldString += ', NOT deletable by viewer' - $false + if ($PSBoundParameters.ContainsKey('RetrievalStep')) { + $passVals.retrieval_step = [bool]$RetrievalStep + $shouldString += $RetrievalStep ? ', with a 1-click retrieval step' : ', without a retrieval step' } - $body.password.retrieval_step = if ($RetrievalStep) { - $shouldString += ', with a 1-click retrieval step' - $true + + if ($File) { + $_Files = Get-ChildItem -Path $File + Write-Debug "Attaching $($_Files.Name -join '; ')" + if ($_Files.Count -gt 10) { + Write-Error "The total number of files is greater than allowed. Only 10 files may be attached to each Push." -ErrorAction Stop + } + else { + $shouldString += ", attaching $($_Files.count) files" + } + $Form = @{ } + $passVals.GetEnumerator() | ForEach-Object { $Form.Add("password[$($_.Name)]", $_.Value) } + $Form.'password[files][]' = $_Files + if ($AccountId) { + $Form.account_id = $AccountId + $shouldString += ', with account ID {0}' -f $AccountId + } + Write-Debug "Form looks like $($Form | Out-String)" + $invokeSplat = @{ + Form = $Form + } } else { - $shouldString += ', with a direct link' - $false + $Body = @{ 'password' = $passVals } + if ($AccountId) { + $Body.account_id = $AccountId + $shouldString += ', with account ID {0}' -f $AccountId + } + Write-Debug "Body looks like $($Body | ConvertTo-Json -Depth 5)" + $invokeSplat = @{ + Body = $Body + } } - if ($PSCmdlet.ShouldProcess($shouldString, $iwrSplat.Uri, 'Submit new Push')) { - $response = Invoke-PasswordPusherAPI -Endpoint 'p.json' -Method Post -Body $body + if ($PSCmdlet.ShouldProcess($shouldString, $Script:PPPBaseUrl, 'Submit new Push')) { + $response = Invoke-PasswordPusherAPI -Endpoint 'p.json' -Method Post @invokeSplat $response | ConvertTo-PasswordPush } } } -#EndRegion '.\Public\New-Push.ps1' 173 +#EndRegion '.\Public\New-Push.ps1' 268 #Region '.\Public\Remove-Push.ps1' -1 <# From c2779dc04690c2b0600a202b805663460a3fa3f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= <31723128+kris6673@users.noreply.github.com> Date: Thu, 27 Feb 2025 11:17:08 +0100 Subject: [PATCH 080/167] remove file --- .../Invoke-ListGenericAllTenants.ps1 | 54 ------------------- 1 file changed, 54 deletions(-) delete mode 100644 Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericAllTenants.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericAllTenants.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericAllTenants.ps1 deleted file mode 100644 index e8cdc66c8df8..000000000000 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericAllTenants.ps1 +++ /dev/null @@ -1,54 +0,0 @@ -using namespace System.Net - -Function Invoke-ListGenericAllTenants { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - CIPP.Core.Read - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - - # XXX This feels like an unused endpoint to me. -Bobby - - $TableURLName = ($QueueItem.tolower().split('?').Split('/') | Select-Object -First 1).toString() - $QueueKey = (Invoke-ListCippQueue | Where-Object -Property Name -EQ $TableURLName | Select-Object -Last 1).RowKey - Update-CippQueueEntry -RowKey $QueueKey -Status 'Started' - $Table = Get-CIPPTable -TableName "cache$TableURLName" - $fullUrl = "https://graph.microsoft.com/beta/$QueueItem" - Get-CIPPAzDataTableEntity @Table | Remove-AzDataTableEntity -Force @table - - $RawGraphRequest = Get-Tenants | ForEach-Object -Parallel { - $domainName = $_.defaultDomainName - Import-Module '.\Modules\AzBobbyTables' - Import-Module '.\Modules\CIPPCore' - try { - Write-Host $using:fullUrl - New-GraphGetRequest -uri $using:fullUrl -tenantid $_.defaultDomainName -ComplexFilter -ErrorAction Stop | Select-Object *, @{l = 'Tenant'; e = { $domainName } }, @{l = 'CippStatus'; e = { 'Good' } } - } catch { - [PSCustomObject]@{ - Tenant = $domainName - CippStatus = "Could not connect to tenant. $($_.Exception.message)" - } - } - } - - Update-CippQueueEntry -RowKey $QueueKey -Status 'Processing' - foreach ($Request in $RawGraphRequest) { - $Json = ConvertTo-Json -Compress -InputObject $request - $GraphRequest = [PSCustomObject]@{ - Tenant = [string]$Request.tenant - RowKey = [string](New-Guid) - PartitionKey = [string]$URL - Data = [string]$Json - - } - Add-CIPPAzDataTableEntity @Table -Entity $GraphRequest -Force | Out-Null - } - - - Update-CippQueueEntry -RowKey $QueueKey -Status 'Completed' - -} From 0f9df4b00a69c91c58488edb47a9978eb1e1b130 Mon Sep 17 00:00:00 2001 From: Esco Date: Thu, 27 Feb 2025 13:13:24 +0100 Subject: [PATCH 081/167] feat: more SpamFilter options --- .../Invoke-CIPPStandardSpamFilterPolicy.ps1 | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 index 3c5bc4a59466..c46b4f4ca0cf 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 @@ -56,6 +56,15 @@ function Invoke-CIPPStandardSpamFilterPolicy { $PhishQuarantineTag = $Settings.PhishQuarantineTag.value ?? $Settings.PhishQuarantineTag $HighConfidencePhishQuarantineTag = $Settings.HighConfidencePhishQuarantineTag.value ?? $Settings.HighConfidencePhishQuarantineTag + $IncreaseScoreWithImageLinks = if ($Settings.IncreaseScoreWithImageLinks) { 'On' } else { 'Off' } + $IncreaseScoreWithBizOrInfoUrls = if ($Settings.IncreaseScoreWithBizOrInfoUrls) { 'On' } else { 'Off' } + $MarkAsSpamFramesInHtml = if ($Settings.MarkAsSpamFramesInHtml) { 'On' } else { 'Off' } + $MarkAsSpamObjectTagsInHtml = if ($Settings.MarkAsSpamObjectTagsInHtml) { 'On' } else { 'Off' } + $MarkAsSpamEmbedTagsInHtml = if ($Settings.MarkAsSpamEmbedTagsInHtml) { 'On' } else { 'Off' } + $MarkAsSpamFormTagsInHtml = if ($Settings.MarkAsSpamFormTagsInHtml) { 'On' } else { 'Off' } + $MarkAsSpamWebBugsInHtml = if ($Settings.MarkAsSpamWebBugsInHtml) { 'On' } else { 'Off' } + $MarkAsSpamSensitiveWordList = if ($Settings.MarkAsSpamSensitiveWordList) { 'On' } else { 'Off' } + $StateIsCorrect = ($CurrentState.Name -eq $PolicyName) -and ($CurrentState.SpamAction -eq $SpamAction) -and ($CurrentState.SpamQuarantineTag -eq $SpamQuarantineTag) -and @@ -69,17 +78,29 @@ function Invoke-CIPPStandardSpamFilterPolicy { ($CurrentState.HighConfidencePhishQuarantineTag -eq $HighConfidencePhishQuarantineTag) -and ($CurrentState.BulkThreshold -eq $Settings.BulkThreshold) -and ($CurrentState.QuarantineRetentionPeriod -eq 30) -and + ($CurrentState.IncreaseScoreWithImageLinks -eq $IncreaseScoreWithImageLinks) -and ($CurrentState.IncreaseScoreWithNumericIps -eq 'On') -and ($CurrentState.IncreaseScoreWithRedirectToOtherPort -eq 'On') -and + ($CurrentState.IncreaseScoreWithBizOrInfoUrls -eq $IncreaseScoreWithBizOrInfoUrls) -and ($CurrentState.MarkAsSpamEmptyMessages -eq 'On') -and ($CurrentState.MarkAsSpamJavaScriptInHtml -eq 'On') -and + ($CurrentState.MarkAsSpamFramesInHtml -eq $MarkAsSpamFramesInHtml) -and + ($CurrentState.MarkAsSpamObjectTagsInHtml -eq $MarkAsSpamObjectTagsInHtml) -and + ($CurrentState.MarkAsSpamEmbedTagsInHtml -eq $MarkAsSpamEmbedTagsInHtml) -and + ($CurrentState.MarkAsSpamFormTagsInHtml -eq $MarkAsSpamFormTagsInHtml) -and + ($CurrentState.MarkAsSpamWebBugsInHtml -eq $MarkAsSpamWebBugsInHtml) -and + ($CurrentState.MarkAsSpamSensitiveWordList -eq $MarkAsSpamSensitiveWordList) -and ($CurrentState.MarkAsSpamSpfRecordHardFail -eq 'On') -and ($CurrentState.MarkAsSpamFromAddressAuthFail -eq 'On') -and ($CurrentState.MarkAsSpamNdrBackscatter -eq 'On') -and ($CurrentState.MarkAsSpamBulkMail -eq 'On') -and ($CurrentState.InlineSafetyTipsEnabled -eq $true) -and ($CurrentState.PhishZapEnabled -eq $true) -and - ($CurrentState.SpamZapEnabled -eq $true) + ($CurrentState.SpamZapEnabled -eq $true) -and + ($CurrentState.EnableLanguageBlockList -eq $Settings.EnableLanguageBlockList) -and + ((-not $CurrentState.LanguageBlockList -and -not $Settings.LanguageBlockList.value) -or (!(Compare-Object -ReferenceObject $CurrentState.LanguageBlockList -DifferenceObject $Settings.LanguageBlockList.value))) -and + ($CurrentState.EnableRegionBlockList -eq $Settings.EnableRegionBlockList) -and + ((-not $CurrentState.RegionBlockList -and -not $Settings.RegionBlockList.value) -or (!(Compare-Object -ReferenceObject $CurrentState.RegionBlockList -DifferenceObject $Settings.RegionBlockList.value))) $AcceptedDomains = New-ExoRequest -TenantId $Tenant -cmdlet 'Get-AcceptedDomain' @@ -109,10 +130,18 @@ function Invoke-CIPPStandardSpamFilterPolicy { HighConfidencePhishQuarantineTag = $HighConfidencePhishQuarantineTag BulkThreshold = $Settings.BulkThreshold QuarantineRetentionPeriod = 30 + IncreaseScoreWithImageLinks = $IncreaseScoreWithImageLinks IncreaseScoreWithNumericIps = 'On' IncreaseScoreWithRedirectToOtherPort = 'On' + IncreaseScoreWithBizOrInfoUrls = $IncreaseScoreWithBizOrInfoUrls MarkAsSpamEmptyMessages = 'On' MarkAsSpamJavaScriptInHtml = 'On' + MarkAsSpamFramesInHtml = $MarkAsSpamFramesInHtml + MarkAsSpamObjectTagsInHtml = $MarkAsSpamObjectTagsInHtml + MarkAsSpamEmbedTagsInHtml = $MarkAsSpamEmbedTagsInHtml + MarkAsSpamFormTagsInHtml = $MarkAsSpamFormTagsInHtml + MarkAsSpamWebBugsInHtml = $MarkAsSpamWebBugsInHtml + MarkAsSpamSensitiveWordList = $MarkAsSpamSensitiveWordList MarkAsSpamSpfRecordHardFail = 'On' MarkAsSpamFromAddressAuthFail = 'On' MarkAsSpamNdrBackscatter = 'On' @@ -120,9 +149,11 @@ function Invoke-CIPPStandardSpamFilterPolicy { InlineSafetyTipsEnabled = $true PhishZapEnabled = $true SpamZapEnabled = $true + EnableLanguageBlockList = $Settings.EnableLanguageBlockList + LanguageBlockList = $Settings.LanguageBlockList.value + EnableRegionBlockList = $Settings.EnableRegionBlockList + RegionBlockList = $Settings.RegionBlockList.value } - Write-Host '================== DEBUG ==================' - Write-Host $cmdParams if ($CurrentState.Name -eq $PolicyName) { try { From bcabee69437407272f06321b034b9457afcdeba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Thu, 27 Feb 2025 18:45:01 +0100 Subject: [PATCH 082/167] remove the added things again --- .../Email-Exchange/Invoke-ListCalendarPermissions.ps1 | 2 -- 1 file changed, 2 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListCalendarPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListCalendarPermissions.ps1 index 45412db74533..a13f9655c0dc 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListCalendarPermissions.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListCalendarPermissions.ps1 @@ -22,8 +22,6 @@ Function Invoke-ListCalendarPermissions { $CalendarFolder = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-MailboxFolderStatistics' -anchor $UserID -cmdParams $GetCalParam | Select-Object -First 1 -ExcludeProperty *data.type* $CalParam = @{Identity = "$($UserID):\$($CalendarFolder.name)" } $GraphRequest = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-MailboxFolderPermission' -anchor $UserID -cmdParams $CalParam -UseSystemMailbox $true | Select-Object Identity, User, AccessRights, FolderName - $GraphRequest | Add-Member -MemberType NoteProperty -Name 'UserID' -Value $UserID - $GraphRequest | Add-Member -MemberType NoteProperty -Name 'ExchangeGUID' -Value $CalendarFolder.ContentMailboxGuid Write-LogMessage -API $APIName -tenant $TenantFilter -message "Calendar permissions listed for $($TenantFilter)" -sev Debug $StatusCode = [HttpStatusCode]::OK } catch { From cc9fc3df6db5b96a480fe650af920ccfffba3010 Mon Sep 17 00:00:00 2001 From: Mark Heydon Date: Thu, 27 Feb 2025 18:10:54 +0000 Subject: [PATCH 083/167] Fixed App Protection policy assignment and group exclusions from Standards run. --- .../Endpoint/MEM/Invoke-AddPolicy.ps1 | 3 +- .../Public/Set-CIPPAssignedPolicy.ps1 | 24 +++++---- .../CIPPCore/Public/Set-CIPPIntunePolicy.ps1 | 52 +++++++++++-------- .../Invoke-CIPPStandardIntuneTemplate.ps1 | 7 +-- 4 files changed, 47 insertions(+), 39 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddPolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddPolicy.ps1 index 5cf66fec102d..67fcdae69680 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddPolicy.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddPolicy.ps1 @@ -18,6 +18,7 @@ Function Invoke-AddPolicy { $displayname = $Request.Body.displayName $description = $Request.Body.Description $AssignTo = if ($Request.Body.AssignTo -ne 'on') { $Request.Body.AssignTo } + $ExcludeGroup = $Request.Body.excludeGroup $Request.body.customGroup ? ($AssignTo = $Request.body.customGroup) : $null $RawJSON = $Request.Body.RAWJson @@ -27,7 +28,7 @@ Function Invoke-AddPolicy { } try { Write-Host 'Calling Adding policy' - Set-CIPPIntunePolicy -TemplateType $Request.body.TemplateType -Description $description -DisplayName $displayname -RawJSON $RawJSON -AssignTo $AssignTo -tenantFilter $Tenant -Headers $Request.Headers + Set-CIPPIntunePolicy -TemplateType $Request.body.TemplateType -Description $description -DisplayName $displayname -RawJSON $RawJSON -AssignTo $AssignTo -ExcludeGroup $ExcludeGroup -tenantFilter $Tenant -Headers $Request.Headers Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($Tenant) -message "Added policy $($Displayname)" -Sev 'Info' } catch { "$($_.Exception.Message)" diff --git a/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 b/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 index 5386bd8dff9a..f44f5616fa4f 100644 --- a/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 @@ -2,17 +2,16 @@ function Set-CIPPAssignedPolicy { [CmdletBinding(SupportsShouldProcess = $true)] param( $GroupName, - $excludeGroup, + $ExcludeGroup, $PolicyId, $Type, $TenantFilter, - $PlatformType, + $PlatformType = 'deviceManagement', $APIName = 'Assign Policy', $Headers ) - if (!$PlatformType) { - $PlatformType = 'deviceManagement' - } + + Write-Host "Assigning policy $PolicyId ($PlatformType/$Type) to $GroupName" try { $assignmentsList = New-Object System.Collections.Generic.List[System.Object] @@ -74,8 +73,9 @@ function Set-CIPPAssignedPolicy { } } } - if ($excludeGroup) { - $ExcludeGroupNames = $excludeGroup.Split(',') + if ($ExcludeGroup) { + Write-Host "We're supposed to exclude a custom group. The group is $ExcludeGroup" + $ExcludeGroupNames = $ExcludeGroup.Split(',') $ExcludeGroupIds = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/groups?$select=id,displayName&$top=999' -tenantid $TenantFilter | ForEach-Object { foreach ($SingleName in $ExcludeGroupNames) { @@ -104,9 +104,13 @@ function Set-CIPPAssignedPolicy { $AssignJSON = $assignmentsObject | ConvertTo-Json -Depth 10 -Compress Write-Host "AssignJSON: $AssignJSON" if ($PSCmdlet.ShouldProcess($GroupName, "Assigning policy $PolicyId")) { - Write-Host "https://graph.microsoft.com/beta/$($PlatformType)/$Type('$($PolicyId)')/assign" - $null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$($PlatformType)/$Type('$($PolicyId)')/assign" -tenantid $TenantFilter -type POST -body $AssignJSON - Write-LogMessage -headers $Headers -API $APIName -message "Assigned $GroupName and excluded $excludeGroup to Policy $PolicyId" -Sev 'Info' -tenant $TenantFilter + $uri = "https://graph.microsoft.com/beta/$($PlatformType)/$Type('$($PolicyId)')/assign" + $null = New-GraphPOSTRequest -uri $uri -tenantid $TenantFilter -type POST -body $AssignJSON + if ($ExcludeGroup) { + Write-LogMessage -headers $Headers -API $APIName -message "Assigned group '$GroupName' and excluded group '$ExcludeGroup' on Policy $PolicyId" -Sev 'Info' -tenant $TenantFilter + } else { + Write-LogMessage -headers $Headers -API $APIName -message "Assigned group '$GroupName' on Policy $PolicyId" -Sev 'Info' -tenant $TenantFilter + } } } catch { diff --git a/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1 b/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1 index 64c51dfd5db5..abc3941896f6 100644 --- a/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1 @@ -6,7 +6,7 @@ function Set-CIPPIntunePolicy { $DisplayName, $RawJSON, $AssignTo, - $excludeGroup, + $ExcludeGroup, $Headers, $APINAME, $tenantFilter @@ -14,118 +14,124 @@ function Set-CIPPIntunePolicy { try { switch ($TemplateType) { 'AppProtection' { + $PlatformType = 'deviceAppManagement' $TemplateType = ($RawJSON | ConvertFrom-Json).'@odata.type' -replace '#microsoft.graph.', '' $PolicyFile = $RawJSON | ConvertFrom-Json $Null = $PolicyFile | Add-Member -MemberType NoteProperty -Name 'description' -Value $description -Force $null = $PolicyFile | Add-Member -MemberType NoteProperty -Name 'displayName' -Value $displayname -Force $RawJSON = ConvertTo-Json -InputObject $PolicyFile -Depth 20 $TemplateTypeURL = if ($TemplateType -eq 'windowsInformationProtectionPolicy') { 'windowsInformationProtectionPolicies' } else { "$($TemplateType)s" } - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/$TemplateTypeURL" -tenantid $tenantFilter + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter if ($displayname -in $CheckExististing.displayName) { $PostType = 'edited' $ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $displayname - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenantFilter -type PATCH -body $RawJSON + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenantFilter -type PATCH -body $RawJSON $CreateRequest = $CheckExististing | Where-Object -Property displayName -EQ $DisplayName } else { $PostType = 'added' - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceAppManagement/$TemplateTypeURL" -tenantid $tenantFilter -type POST -body $RawJSON + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter -type POST -body $RawJSON } } 'deviceCompliancePolicies' { + $PlatformType = 'deviceManagement' $TemplateTypeURL = 'deviceCompliancePolicies' - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenantFilter + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter $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') if ($displayname -in $CheckExististing.displayName) { $RawJSON = ConvertTo-Json -InputObject ($JSON | Select-Object * -ExcludeProperty 'scheduledActionsForRule') -Depth 20 -Compress $PostType = 'edited' $ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $displayname - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenantFilter -type PATCH -body $RawJSON + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenantFilter -type PATCH -body $RawJSON Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenantFilter) -message "Updated policy $($DisplayName) to template defaults" -Sev 'info' $CreateRequest = $CheckExististing | Where-Object -Property displayName -EQ $DisplayName } else { $RawJSON = ConvertTo-Json -InputObject $JSON -Depth 20 -Compress $PostType = 'added' - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenantFilter -type POST -body $RawJSON + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter -type POST -body $RawJSON Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenantFilter) -message "Added policy $($DisplayName) via template" -Sev 'info' } } 'Admin' { + $PlatformType = 'deviceManagement' $TemplateTypeURL = 'groupPolicyConfigurations' $CreateBody = '{"description":"' + $description + '","displayName":"' + $displayname + '","roleScopeTagIds":["0"]}' - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenantFilter + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter 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 $tenantFilter + $ExistingData = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL('$($ExistingID.id)')/definitionValues" -tenantid $tenantFilter $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 $tenantFilter -type POST -body $DeleteJson - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($ExistingID.id)')/updateDefinitionValues" -tenantid $tenantFilter -type POST -body $RawJSON + $DeleteRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL('$($ExistingID.id)')/updateDefinitionValues" -tenantid $tenantFilter -type POST -body $DeleteJson + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL('$($ExistingID.id)')/updateDefinitionValues" -tenantid $tenantFilter -type POST -body $RawJSON $CreateRequest = $CheckExististing | Where-Object -Property displayName -EQ $DisplayName Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenantFilter) -message "Updated policy $($Displayname) to template defaults" -Sev 'info' $PostType = 'edited' } else { $PostType = 'added' - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenantFilter -type POST -body $CreateBody - $UpdateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL('$($CreateRequest.id)')/updateDefinitionValues" -tenantid $tenantFilter -type POST -body $RawJSON + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter -type POST -body $CreateBody + $UpdateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL('$($CreateRequest.id)')/updateDefinitionValues" -tenantid $tenantFilter -type POST -body $RawJSON Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenantFilter) -message "Added policy $($Displayname) to template defaults" -Sev 'info' } } 'Device' { + $PlatformType = 'deviceManagement' $TemplateTypeURL = 'deviceConfigurations' $PolicyFile = $RawJSON | ConvertFrom-Json $Null = $PolicyFile | Add-Member -MemberType NoteProperty -Name 'description' -Value "$description" -Force $null = $PolicyFile | Add-Member -MemberType NoteProperty -Name 'displayName' -Value $displayname -Force - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenantFilter + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter $ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $DisplayName | Select-Object -Last 1 $PolicyFile = $policyFile | Select-Object * -ExcludeProperty 'featureUpdatesWillBeRolledBack', 'qualityUpdatesWillBeRolledBack', 'qualityUpdatesPauseStartDate', 'featureUpdatesPauseStartDate' $RawJSON = ConvertTo-Json -InputObject $PolicyFile -Depth 100 -Compress if ($ExistingID) { $PostType = 'edited' Write-Host "Raw JSON is $RawJSON" - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenantFilter -type PATCH -body $RawJSON + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenantFilter -type PATCH -body $RawJSON $CreateRequest = $CheckExististing | Where-Object -Property displayName -EQ $DisplayName Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenantFilter) -message "Updated policy $($DisplayName) to template defaults" -Sev 'info' } else { $PostType = 'added' - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenantFilter -type POST -body $RawJSON + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter -type POST -body $RawJSON Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenantFilter) -message "Added policy $($DisplayName) via template" -Sev 'info' } } 'Catalog' { + $PlatformType = 'deviceManagement' $TemplateTypeURL = 'configurationPolicies' $DisplayName = ($RawJSON | ConvertFrom-Json).Name - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenantFilter + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter if ($DisplayName -in $CheckExististing.name) { $ExistingID = $CheckExististing | Where-Object -Property Name -EQ $DisplayName - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenantFilter -type PUT -body $RawJSON + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenantFilter -type PUT -body $RawJSON $CreateRequest = $CheckExististing | Where-Object -Property Name -EQ $DisplayName $PostType = 'edited' } else { $PostType = 'added' - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenantFilter -type POST -body $RawJSON + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter -type POST -body $RawJSON Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenantFilter) -message "Added policy $($DisplayName) via template" -Sev 'info' } } 'windowsDriverUpdateProfiles' { + $PlatformType = 'deviceManagement' $TemplateTypeURL = 'windowsDriverUpdateProfiles' $File = ($RawJSON | ConvertFrom-Json) $DisplayName = $File.displayName ?? $File.Name - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenantFilter + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter if ($DisplayName -in $CheckExististing.displayName) { $PostType = 'edited' $ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $displayname Write-Host 'We are editing' - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenantFilter -type PUT -body $RawJSON + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenantFilter -type PUT -body $RawJSON $CreateRequest = $CheckExististing | Where-Object -Property displayName -EQ $DisplayName } else { $PostType = 'added' - $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$TemplateTypeURL" -tenantid $tenantFilter -type POST -body $RawJSON + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter -type POST -body $RawJSON Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenantFilter) -message "Added policy $($DisplayName) via template" -Sev 'info' } } @@ -136,7 +142,7 @@ function Set-CIPPIntunePolicy { Write-Host "Assigning policy to $($AssignTo) with ID $($CreateRequest.id) and type $TemplateTypeURL for tenant $tenantFilter" Write-Host "ID is $($CreateRequest.id)" - Set-CIPPAssignedPolicy -GroupName $AssignTo -PolicyId $CreateRequest.id -Type $TemplateTypeURL -TenantFilter $tenantFilter -excludeGroup $excludeGroup + Set-CIPPAssignedPolicy -GroupName $AssignTo -PolicyId $CreateRequest.id -PlatformType $PlatformType -Type $TemplateTypeURL -TenantFilter $tenantFilter -ExcludeGroup $ExcludeGroup } return "Successfully $($PostType) policy for $($tenantFilter) with display name $($Displayname)" } catch { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 index 361073a2f21f..372fa302a177 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 @@ -15,16 +15,13 @@ function Invoke-CIPPStandardIntuneTemplate { MULTIPLE True DISABLEDFEATURES - + IMPACT High Impact - ADDEDDATE - 2023-12-30 ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"creatable":false,"name":"TemplateList","label":"Select Intune Template","api":{"url":"/api/ListIntuneTemplates","labelField":"Displayname","valueField":"GUID","queryKey":"languages"}} {"name":"AssignTo","label":"Who should this template be assigned to?","type":"radio","options":[{"label":"Do not assign","value":"On"},{"label":"Assign to all users","value":"allLicensedUsers"},{"label":"Assign to all devices","value":"AllDevices"},{"label":"Assign to all users and devices","value":"AllDevicesAndUsers"},{"label":"Assign to Custom Group","value":"customGroup"}]} {"type":"textField","required":false,"name":"customGroup","label":"Enter the custom group name if you selected 'Assign to Custom Group'. Wildcards are allowed."} - {"name":"excludeGroup","label":"Exclude Groups","type":"textField","required":false,"helpText":"Enter the group name to exclude from the assignment. Wildcards are allowed."} UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK @@ -49,7 +46,7 @@ function Invoke-CIPPStandardIntuneTemplate { $description = $request.body.Description $RawJSON = $Request.body.RawJSON $Template.customGroup ? ($Template.AssignTo = $Template.customGroup) : $null - Set-CIPPIntunePolicy -TemplateType $Request.body.Type -Description $description -DisplayName $displayname -RawJSON $RawJSON -AssignTo $Template.AssignTo -excludeGroup $Template.excludeGroup -tenantFilter $Tenant + Set-CIPPIntunePolicy -TemplateType $Request.body.Type -Description $description -DisplayName $displayname -RawJSON $RawJSON -AssignTo $Template.AssignTo -ExcludeGroup $Template.excludeGroup -tenantFilter $Tenant } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message From b7000b05000cc886c591f74eef941e9f03bcfec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Thu, 27 Feb 2025 19:12:24 +0100 Subject: [PATCH 084/167] friendship with ArchiveStatus over, ArchiveGuid is best friend now --- .../Users/Invoke-ListUserMailboxDetails.ps1 | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxDetails.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxDetails.ps1 index aaf54bd1bf09..cac7e39d7514 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxDetails.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxDetails.ps1 @@ -11,13 +11,12 @@ Function Invoke-ListUserMailboxDetails { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' # Interact with query parameters or the body of the request. - $TenantFilter = $Request.Query.TenantFilter + $TenantFilter = $Request.Query.tenantFilter $UserID = $Request.Query.UserID try { @@ -76,15 +75,15 @@ Function Invoke-ListUserMailboxDetails { $ArchiveSizeRequest = $Results.'Get-MailboxStatistics' $BlockedSender = $Results.'Get-BlockedSenderAddress' $PermsRequest2 = $Results.'Get-RecipientPermission' - $StatsRequest = New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($tenantfilter)/Mailbox('$($MailboxDetailedRequest.UserPrincipalName)')/Exchange.GetMailboxStatistics()" -Tenantid $tenantfilter -scope ExchangeOnline -noPagination $true + $StatsRequest = New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($TenantFilter)/Mailbox('$($MailboxDetailedRequest.UserPrincipalName)')/Exchange.GetMailboxStatistics()" -Tenantid $TenantFilter -scope ExchangeOnline -noPagination $true # Handle ArchiveEnabled and AutoExpandingArchiveEnabled try { - if ($MailboxDetailedRequest.ArchiveStatus -eq 'Active') { - $ArchiveEnabled = $True + if ($MailboxDetailedRequest.ArchiveGuid -ne '00000000-0000-0000-0000-000000000000') { + $ArchiveEnabled = $true } else { - $ArchiveEnabled = $False + $ArchiveEnabled = $false } # Get organization config of auto-expanding archive if it's disabled on user level @@ -94,7 +93,7 @@ Function Invoke-ListUserMailboxDetails { $AutoExpandingArchiveEnabled = $MailboxDetailedRequest.AutoExpandingArchiveEnabled } } catch { - $ArchiveEnabled = $False + $ArchiveEnabled = $false $ArchiveSizeRequest = @{ TotalItemSize = '0' ItemCount = '0' @@ -155,7 +154,7 @@ Function Invoke-ListUserMailboxDetails { $ItemSizeType = '1{0}' -f ($TotalItemSizeString[1] ?? 'Gb') $TotalItemSize = try { [math]::Round([float]($TotalItemSizeString[0]) / $ItemSizeType, 2) } catch { 0 } - if ($ArchiveEnabled) { + if ($ArchiveEnabled -eq $true) { $TotalArchiveItemSize = try { [math]::Round([float]($TotalArchiveItemSizeString[0]), 2) } catch { 0 } $TotalArchiveItemCount = try { [math]::Round($ArchiveSizeRequest.ItemCount, 2) } catch { 0 } } From 16b314c1892d3344b1542eafd85e908d6b4e3f87 Mon Sep 17 00:00:00 2001 From: Mark Heydon Date: Thu, 27 Feb 2025 18:22:20 +0000 Subject: [PATCH 085/167] Slightly mangled comment block. --- .../Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 index 372fa302a177..c597958af7cf 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 @@ -18,10 +18,13 @@ function Invoke-CIPPStandardIntuneTemplate { IMPACT High Impact + ADDEDDATE + 2023-12-30 ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"creatable":false,"name":"TemplateList","label":"Select Intune Template","api":{"url":"/api/ListIntuneTemplates","labelField":"Displayname","valueField":"GUID","queryKey":"languages"}} {"name":"AssignTo","label":"Who should this template be assigned to?","type":"radio","options":[{"label":"Do not assign","value":"On"},{"label":"Assign to all users","value":"allLicensedUsers"},{"label":"Assign to all devices","value":"AllDevices"},{"label":"Assign to all users and devices","value":"AllDevicesAndUsers"},{"label":"Assign to Custom Group","value":"customGroup"}]} {"type":"textField","required":false,"name":"customGroup","label":"Enter the custom group name if you selected 'Assign to Custom Group'. Wildcards are allowed."} + {"name":"ExcludeGroup","label":"Exclude Groups","type":"textField","required":false,"helpText":"Enter the group name to exclude from the assignment. Wildcards are allowed."} UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK From 9ecad4b4e8721c8517e91437d6e9fe9fc2d49aa6 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Thu, 27 Feb 2025 16:29:17 -0500 Subject: [PATCH 086/167] chore: refactor ninja sync to improve performance reduce api calls to graph/exchange and rely on cached data from extension sync fix standards reporting to use new template engine update URLs accordingly --- .../Invoke-ExecExtensionMapping.ps1 | 2 + .../Start-ExtensionOrchestrator.ps1 | 2 +- .../Webhooks/New-CIPPGraphSubscription.ps1 | 3 + .../Invoke-NinjaOneExtensionScheduler.ps1 | 6 +- .../NinjaOne/Invoke-NinjaOneTenantSync.ps1 | 405 +++++------------- 5 files changed, 114 insertions(+), 304 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionMapping.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionMapping.ps1 index 3fbb1ac29ccf..dbd93185d239 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionMapping.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionMapping.ps1 @@ -62,9 +62,11 @@ Function Invoke-ExecExtensionMapping { } 'NinjaOne' { $Body = Set-NinjaOneOrgMapping -CIPPMapping $Table -APIName $APIName -Request $Request + Register-CIPPExtensionScheduledTasks } 'NinjaOneFields' { $Body = Set-NinjaOneFieldMapping -CIPPMapping $Table -APIName $APIName -Request $Request -TriggerMetadata $TriggerMetadata + Register-CIPPExtensionScheduledTasks } 'Hudu' { $Body = Set-HuduMapping -CIPPMapping $Table -APIName $APIName -Request $Request diff --git a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-ExtensionOrchestrator.ps1 b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-ExtensionOrchestrator.ps1 index 55126c5080ca..9d6fa6a119b7 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-ExtensionOrchestrator.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-ExtensionOrchestrator.ps1 @@ -15,7 +15,7 @@ function Start-ExtensionOrchestrator { Write-Host 'Started Scheduler for Extensions' # NinjaOne Extension - if ($Configuration.NinjaOne.Enabled -eq $True) { + if ($Configuration.NinjaOne.Enabled -eq $true) { if ($PSCmdlet.ShouldProcess('Invoke-NinjaOneExtensionScheduler')) { Invoke-NinjaOneExtensionScheduler } diff --git a/Modules/CIPPCore/Public/Webhooks/New-CIPPGraphSubscription.ps1 b/Modules/CIPPCore/Public/Webhooks/New-CIPPGraphSubscription.ps1 index a68ab8923a8b..2e32b90c2de2 100644 --- a/Modules/CIPPCore/Public/Webhooks/New-CIPPGraphSubscription.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/New-CIPPGraphSubscription.ps1 @@ -93,6 +93,9 @@ function New-CIPPGraphSubscription { expirationDateTime = $expiredate } | ConvertTo-Json + if ($BaseURL -match 'localhost' -or $BaseURL -match '127.0.0.1') { + return 'Cannot create graph subscription for local development' + } $GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/subscriptions' -tenantid $TenantFilter -type POST -body $params -verbose #If creation is succesfull, we store the GUID in the storage table webhookTable to make sure we can check against this later on. diff --git a/Modules/CippExtensions/Public/NinjaOne/Invoke-NinjaOneExtensionScheduler.ps1 b/Modules/CippExtensions/Public/NinjaOne/Invoke-NinjaOneExtensionScheduler.ps1 index 921a6d1e1ac3..fddf4c1666a4 100644 --- a/Modules/CippExtensions/Public/NinjaOne/Invoke-NinjaOneExtensionScheduler.ps1 +++ b/Modules/CippExtensions/Public/NinjaOne/Invoke-NinjaOneExtensionScheduler.ps1 @@ -16,7 +16,11 @@ function Invoke-NinjaOneExtensionScheduler { Write-Host "Ninja Time Setting: $TimeSetting" - $LastRunTime = Get-Date(($Settings | Where-Object { $_.RowKey -eq 'NinjaLastRunTime' }).SettingValue) + try { + $LastRunTime = Get-Date(($Settings | Where-Object { $_.RowKey -eq 'NinjaLastRunTime' }).SettingValue) + } catch { + $LastRunTime = $Null + } Write-Host "Last Run: $LastRunTime" diff --git a/Modules/CippExtensions/Public/NinjaOne/Invoke-NinjaOneTenantSync.ps1 b/Modules/CippExtensions/Public/NinjaOne/Invoke-NinjaOneTenantSync.ps1 index 813ce65b3af5..7f5826e18556 100644 --- a/Modules/CippExtensions/Public/NinjaOne/Invoke-NinjaOneTenantSync.ps1 +++ b/Modules/CippExtensions/Public/NinjaOne/Invoke-NinjaOneTenantSync.ps1 @@ -274,92 +274,29 @@ function Invoke-NinjaOneTenantSync { [System.Collections.Generic.List[PSCustomObject]]$NinjaLicenseUpdates = @() [System.Collections.Generic.List[PSCustomObject]]$NinjaLicenseCreation = @() - # Build bulk requests array. - [System.Collections.Generic.List[PSCustomObject]]$TenantRequests = @( - @{ - id = 'Users' - method = 'GET' - url = '/users?$top=999' - }, - @{ - id = 'TenantDetails' - method = 'GET' - url = '/organization' - }, - @{ - id = 'AllRoles' - method = 'GET' - url = '/directoryRoles' - }, - @{ - id = 'RawDomains' - method = 'GET' - url = '/domains' - }, - @{ - id = 'Licenses' - method = 'GET' - url = '/subscribedSkus' - }, - @{ - id = 'Devices' - method = 'GET' - url = '/deviceManagement/managedDevices?$top=999' - }, - @{ - id = 'DeviceCompliancePolicies' - method = 'GET' - url = '/deviceManagement/deviceCompliancePolicies/' - }, - <#@{ - id = 'DeviceApps' - method = 'GET' - url = '/deviceAppManagement/mobileApps' - },#> - @{ - id = 'Groups' - method = 'GET' - url = '/groups' - }, - @{ - id = 'ConditionalAccess' - method = 'GET' - url = '/identity/conditionalAccess/policies' - }, - @{ - id = 'SecureScore' - method = 'GET' - url = '/security/secureScores?$top=999' - }, - @{ - id = 'SecureScoreControlProfiles' - method = 'GET' - url = '/security/secureScoreControlProfiles?$top=999' - }, - @{ - id = 'Subscriptions' - method = 'GET' - url = '/directory/subscriptions' - } - - ) - - Write-Verbose "$(Get-Date) - Fetching Bulk Data" - try { - $TenantResults = New-GraphBulkRequest -Requests $TenantRequests -tenantid $TenantFilter -NoAuthCheck $True - } catch { - Throw "Failed to fetch bulk company data: $_" - } - - Write-Information 'Fetched Bulk M365 Data' - - $Users = Get-GraphBulkResultByID -value -Results $TenantResults -ID 'Users' - - $SecureScore = Get-GraphBulkResultByID -value -Results $TenantResults -ID 'SecureScore' - - $Subscriptions = Get-GraphBulkResultByID -value -Results $TenantResults -ID 'Subscriptions' - - [System.Collections.Generic.List[PSCustomObject]]$SecureScoreProfiles = Get-GraphBulkResultByID -value -Results $TenantResults -ID 'SecureScoreControlProfiles' + # Replace direct Graph/Exchange calls with cached data + $ExtensionCache = Get-ExtensionCacheData -TenantFilter $Customer.defaultDomainName + + # Map cached data to variables + $Users = $ExtensionCache.Users + $licensedUsers = $Users | Where-Object { $null -ne $_.assignedLicenses.skuId } + $AllRoles = $ExtensionCache.AllRoles + $Devices = $ExtensionCache.Devices + $DeviceCompliancePolicies = $ExtensionCache.DeviceCompliancePolicies + $OneDriveDetails = $ExtensionCache.OneDriveUsage + $CASFull = $ExtensionCache.CASMailbox + $MailboxDetailedFull = $ExtensionCache.Mailboxes + $MailboxStatsFull = $ExtensionCache.MailboxUsage + $Permissions = $ExtensionCache.MailboxPermissions + $SecureScore = $ExtensionCache.SecureScore + $Subscriptions = $ExtensionCache.Subscriptions + $SecureScoreProfiles = $ExtensionCache.SecureScoreControlProfiles + $TenantDetails = $ExtensionCache.TenantDetails + $RawDomains = $ExtensionCache.Domains + $AllGroups = $ExtensionCache.Groups + $Licenses = $ExtensionCache.Licenses + $RawDomains = $ExtensionCache.Domains + $AllConditionalAccessPolicies = $ExtensionCache.ConditionalAccessPolicies $CurrentSecureScore = ($SecureScore | Sort-Object createDateTime -Descending | Select-Object -First 1) $MaxSecureScoreRank = ($SecureScoreProfiles.rank | Measure-Object -Maximum).maximum @@ -384,136 +321,58 @@ function Invoke-NinjaOneTenantSync { } } - $TenantDetails = Get-GraphBulkResultByID -value -Results $TenantResults -ID 'TenantDetails' - - Write-Verbose "$(Get-Date) - Parsing Users" # Grab licensed users $licensedUsers = $Users | Where-Object { $null -ne $_.AssignedLicenses.SkuId } | Sort-Object UserPrincipalName - Write-Verbose "$(Get-Date) - Parsing Roles" - # Get All Roles - $AllRoles = Get-GraphBulkResultByID -value -Results $TenantResults -ID 'AllRoles' - - $SelectList = 'id', 'displayName', 'userPrincipalName' - - [System.Collections.Generic.List[PSCustomObject]]$RolesRequestArray = @() - foreach ($Role in $AllRoles) { - $RolesRequestArray.add(@{ - id = $Role.id - method = 'GET' - url = "/directoryRoles/$($Role.id)/members?`$select=$($selectlist -join ',')" - }) - } - - try { - $MemberReturn = New-GraphBulkRequest -Requests $RolesRequestArray -tenantid $TenantFilter -NoAuthCheck $True - } catch { - $MemberReturn = $null - } - - Write-Information 'Fetched M365 Roles' - - $Roles = foreach ($Result in $MemberReturn) { + $Roles = foreach ($Role in $AllRoles) { + # Get members from cache + $Members = ($ExtensionCache."AllRoles_$($Role.id)") [PSCustomObject]@{ ID = $Result.id - DisplayName = ($AllRoles | Where-Object { $_.id -eq $Result.id }).displayName - Description = ($AllRoles | Where-Object { $_.id -eq $Result.id }).description - Members = $Result.body.value - ParsedMembers = $Result.body.value.Displayname -join ', ' + DisplayName = $Role.displayName + Description = $Role.description + Members = $Members + ParsedMembers = $Members.displayName -join ', ' } } - - $AdminUsers = (($Roles | Where-Object { $_.Displayname -match 'Administrator' }).Members | Where-Object { $null -ne $_.displayName }) Write-Verbose "$(Get-Date) - Fetching Domains" - try { - $RawDomains = Get-GraphBulkResultByID -value -Results $TenantResults -ID 'RawDomains' - } catch { - $RawDomains = $null - } - $customerDomains = ($RawDomains | Where-Object { $_.IsVerified -eq $True }).id -join ', ' | Out-String + $customerDomains = ($RawDomains | Where-Object { $_.IsVerified -eq $true }).id -join ', ' | Out-String Write-Verbose "$(Get-Date) - Parsing Licenses" - # Get Licenses - $Licenses = Get-GraphBulkResultByID -value -Results $TenantResults -ID 'Licenses' # Get the license overview for the tenant if ($Licenses) { $LicensesParsed = $Licenses | Where-Object { $_.PrepaidUnits.Enabled -gt 0 } | Select-Object @{N = 'License Name'; E = { (Get-Culture).TextInfo.ToTitleCase((convert-skuname -skuname $_.SkuPartNumber).Tolower()) } }, @{N = 'Active'; E = { $_.PrepaidUnits.Enabled } }, @{N = 'Consumed'; E = { $_.ConsumedUnits } }, @{N = 'Unused'; E = { $_.PrepaidUnits.Enabled - $_.ConsumedUnits } } } - Write-Verbose "$(Get-Date) - Parsing Devices" - # Get all devices from Intune - $devices = Get-GraphBulkResultByID -value -Results $TenantResults -ID 'Devices' - - Write-Verbose "$(Get-Date) - Parsing Device Compliance Polcies" - # Fetch Compliance Policy Status - $DeviceCompliancePolicies = Get-GraphBulkResultByID -value -Results $TenantResults -ID 'DeviceCompliancePolicies' - - # Get the status of each device for each policy - [System.Collections.Generic.List[PSCustomObject]]$PolicyRequestArray = @() - foreach ($CompliancePolicy in $DeviceCompliancePolicies) { - $PolicyRequestArray.add(@{ - id = $CompliancePolicy.id - method = 'GET' - url = "/deviceManagement/deviceCompliancePolicies/$($CompliancePolicy.id)/deviceStatuses" - }) - } - - try { - $PolicyReturn = New-GraphBulkRequest -Requests $PolicyRequestArray -tenantid $TenantFilter -NoAuthCheck $True - } catch { - $PolicyReturn = $null - } - - Write-Information 'Fetched M365 Device Compliance' + Write-Verbose "$(Get-Date) - Parsing Device Compliance Policies" - $DeviceComplianceDetails = foreach ($Result in $PolicyReturn) { + $DeviceComplianceDetails = foreach ($Policy in $DeviceCompliancePolicies) { + $DeviceStatuses = $ExtensionCache."DeviceCompliancePolicy_$($Policy.id)" [pscustomobject]@{ - ID = ($DeviceCompliancePolicies | Where-Object { $_.id -eq $Result.id }).id - DisplayName = ($DeviceCompliancePolicies | Where-Object { $_.id -eq $Result.id }).DisplayName - DeviceStatuses = $Result.body.value + ID = $Policy.id + DisplayName = $Policy.displayName + DeviceStatuses = $DeviceStatuses } } Write-Verbose "$(Get-Date) - Parsing Groups" - # Fetch Groups - $AllGroups = Get-GraphBulkResultByID -value -Results $TenantResults -ID 'Groups' - - # Fetch the App status for each device - [System.Collections.Generic.List[PSCustomObject]]$GroupRequestArray = @() - foreach ($Group in $AllGroups) { - $GroupRequestArray.add(@{ - id = $Group.id - method = 'GET' - url = "/groups/$($Group.id)/members" - }) - } - - try { - $GroupMembersReturn = New-GraphBulkRequest -Requests $GroupRequestArray -tenantid $TenantFilter -NoAuthCheck $True - } catch { - $GroupMembersReturn = $null - } - - Write-Information 'Fetched M365 Group Membership' - $Groups = foreach ($Result in $GroupMembersReturn) { + $Groups = foreach ($Group in $AllGroups) { + $Members = $ExtensionCache."Groups_$($Result.id)" [pscustomobject]@{ - ID = $Result.id - DisplayName = ($AllGroups | Where-Object { $_.id -eq $Result.id }).DisplayName - Members = $result.body.value + ID = $Group.id + DisplayName = $Group.displayName + Members = $Members } } - Write-Verbose "$(Get-Date) - Parsing Conditional Access Polcies" - # Fetch and parse conditional access polcies - $AllConditionalAccessPolcies = Get-GraphBulkResultByID -value -Results $TenantResults -ID 'ConditionalAccess' - $ConditionalAccessMembers = foreach ($CAPolicy in $AllConditionalAccessPolcies) { + $ConditionalAccessMembers = foreach ($CAPolicy in $AllConditionalAccessPolicies) { #Setup User Array [System.Collections.Generic.List[PSCustomObject]]$CAMembers = @() @@ -568,49 +427,6 @@ function Invoke-NinjaOneTenantSync { } } - Write-Verbose "$(Get-Date) - Fetching One Drive Details" - try { - $OneDriveDetails = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/reports/getOneDriveUsageAccountDetail(period='D7')" -tenantid $TenantFilter | ConvertFrom-Csv - } catch { - Write-Error "Failed to fetch Onedrive Details: $_" - $OneDriveDetails = $null - } - - Write-Verbose "$(Get-Date) - Fetching CAS Mailbox Details" - try { - $CASFull = New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($tenantfilter)/CasMailbox" -Tenantid $Customer.defaultDomainName -scope ExchangeOnline -noPagination $true - } catch { - Write-Error "Failed to fetch CAS Details: $_" - $CASFull = $null - } - - Write-Verbose "$(Get-Date) - Fetching Mailbox Details" - try { - $MailboxDetailedFull = New-ExoRequest -TenantID $Customer.defaultDomainName -cmdlet 'Get-Mailbox' - } catch { - Write-Error "Failed to fetch Mailbox Details: $_" - $MailboxDetailedFull = $null - } - - Write-Verbose "$(Get-Date) - Fetching Blocked Mailbox Details" - try { - $BlockedSenders = New-ExoRequest -TenantID $Customer.defaultDomainName -cmdlet 'Get-BlockedSenderAddress' - } catch { - Write-Error "Failed to fetch Blocked Sender Details: $_" - $BlockedSenders = $null - } - - Write-Verbose "$(Get-Date) - Fetching Mailbox Stats" - try { - $MailboxStatsFull = New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/reports/getMailboxUsageDetail(period='D7')" -tenantid $TenantFilter | ConvertFrom-Csv - } catch { - Write-Error "Failed to fetch Mailbox Stats: $_" - $MailboxStatsFull = $null - } - - Write-Information 'Fetched M365 Additional Data' - - $FetchEnd = Get-Date ############################ Format and Synchronize to NinjaOne ############################ @@ -773,7 +589,7 @@ function Invoke-NinjaOneTenantSync { }, @{ Name = 'View Devices in CIPP' - Link = "https://$($CIPPURL)/endpoint/MEM/devices?customerId=$($Customer.defaultDomainName)" + Link = "https://$($CIPPURL)/endpoint/MEM/devices?tenantFilter=$($Customer.defaultDomainName)" Icon = 'far fa-eye' } ) @@ -891,7 +707,6 @@ function Invoke-NinjaOneTenantSync { Write-Information 'Processed Devices' - ########## Create / Update User Objects if ($Configuration.LicensedOnly -eq $True) { @@ -975,20 +790,15 @@ function Invoke-NinjaOneTenantSync { $MailboxDetailedRequest = $MailboxDetailedFull | Where-Object { $_.ExternalDirectoryObjectId -eq $User.iD } $StatsRequest = $MailboxStatsFull | Where-Object { $_.'User Principal Name' -eq $User.UserPrincipalName } - #try { - # $PermsRequest = New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($tenantfilter)/Mailbox('$($User.ID)')/MailboxPermission" -Tenantid $tenantfilter -scope ExchangeOnline -noPagination $true -NoAuthCheck $True - #} catch { - # $PermsRequest = $null - #} - - #$ParsedPerms = foreach ($Perm in $PermsRequest) { - # if ($Perm.User -ne 'NT AUTHORITY\SELF') { - # [pscustomobject]@{ - # User = $Perm.User - # AccessRights = $Perm.PermissionList.AccessRights -join ', ' - # } - # } - #} + + $ParsedPerms = foreach ($Perm in $Permissions) { + if ($Perm.User -ne 'NT AUTHORITY\SELF') { + [pscustomobject]@{ + User = $Perm.User + AccessRights = $Perm.PermissionList.AccessRights -join ', ' + } + } + } try { $TotalItemSize = [math]::Round($StatsRequest.'Storage Used (Byte)' / 1Gb, 2) @@ -1007,7 +817,7 @@ function Invoke-NinjaOneTenantSync { MailboxImapEnabled = $CASRequest.ImapEnabled MailboxPopEnabled = $CASRequest.PopEnabled MailboxActiveSyncEnabled = $CASRequest.ActiveSyncEnabled - #Permissions = $ParsedPerms + Permissions = $ParsedPerms ProhibitSendQuota = [math]::Round([float]($MailboxDetailedRequest.ProhibitSendQuota -split ' GB')[0], 2) ProhibitSendReceiveQuota = [math]::Round([float]($MailboxDetailedRequest.ProhibitSendReceiveQuota -split ' GB')[0], 2) ItemCount = [math]::Round($StatsRequest.'Item Count', 2) @@ -1713,47 +1523,47 @@ function Invoke-NinjaOneTenantSync { $ManagementLinksData = @( @{ Name = 'M365 Admin Portal' - Link = "https://portal.office.com/Partner/BeginClientSession.aspx?CTID=$($customer.CustomerId)&CSDEST=o365admincenter" + Link = "https://portal.office.com/Partner/BeginClientSession.aspx?CTID=$($customer.customerId)&CSDEST=o365admincenter" Icon = 'fas fa-cogs' }, @{ Name = 'Exchange Portal' - Link = "https://admin.exchange.microsoft.com/?landingpage=homepage&form=mac_sidebar&delegatedOrg=$($Customer.DefaultDomainName)#" + Link = "https://admin.exchange.microsoft.com/?landingpage=homepage&form=mac_sidebar&delegatedOrg=$($Customer.defaultDomainName)#" Icon = 'fas fa-mail-bulk' }, @{ Name = 'Entra Portal' - Link = "https://entra.microsoft.com/$($Customer.DefaultDomainName)" + Link = "https://entra.microsoft.com/$($Customer.defaultDomainName)" Icon = 'fas fa-users-cog' }, @{ Name = 'Intune Portal' - Link = "https://endpoint.microsoft.com/$($customer.DefaultDomainName)/" + Link = "https://endpoint.microsoft.com/$($customer.defaultDomainName)/" Icon = 'fas fa-laptop' }, @{ Name = 'Sharepoint Admin' - Link = "https://admin.microsoft.com/Partner/beginclientsession.aspx?CTID=$($Customer.CustomerId)&CSDEST=SharePoint" + Link = "https://admin.microsoft.com/Partner/beginclientsession.aspx?CTID=$($Customer.customerId)&CSDEST=SharePoint" Icon = 'fas fa-shapes' }, @{ Name = 'Teams Admin' - Link = "https://admin.teams.microsoft.com/?delegatedOrg=$($Customer.DefaultDomainName)" + Link = "https://admin.teams.microsoft.com/?delegatedOrg=$($Customer.defaultDomainName)" Icon = 'fas fa-users' }, @{ Name = 'Security Portal' - Link = "https://security.microsoft.com/?tid=$($Customer.CustomerId)" + Link = "https://security.microsoft.com/?tid=$($Customer.customerId)" Icon = 'fas fa-building-shield' }, @{ Name = 'Compliance Portal' - Link = "https://purview.microsoft.com/?tid=$($Customer.CustomerId)" + Link = "https://purview.microsoft.com/?tid=$($Customer.customerId)" Icon = 'fas fa-user-shield' }, @{ Name = 'Azure Portal' - Link = "https://portal.azure.com/$($customer.DefaultDomainName)" + Link = "https://portal.azure.com/$($customer.defaultDomainName)" Icon = 'fas fa-server' } @@ -1765,37 +1575,32 @@ function Invoke-NinjaOneTenantSync { @{ Name = 'CIPP Tenant Dashboard' - Link = "https://$CIPPUrl/home?customerId=$($Customer.CustomerId)" + Link = "https://$CIPPUrl?tenantFilter=$($Customer.defaultDomainName)" Icon = 'fas fa-shield-halved' }, - @{ - Name = 'Edit Tenant' - Link = "https://$CIPPUrl/tenant/administration/tenants/Edit?customerId=$($Customer.customerId)&tenantFilter=$($Customer.defaultDomainName)" - Icon = 'fas fa-cog' - }, @{ Name = 'List Users' - Link = "https://$CIPPUrl/identity/administration/users?customerId=$($Customer.customerId)" + Link = "https://$CIPPUrl/identity/administration/users?tenantFilter=$($Customer.defaultDomainName)" Icon = 'fas fa-user' }, @{ Name = 'List Groups' - Link = "https://$CIPPUrl/identity/administration/groups?customerId=$($Customer.customerId)" + Link = "https://$CIPPUrl/identity/administration/groups?tenantFilter=$($Customer.defaultDomainName)" Icon = 'fas fa-users' }, @{ Name = 'List Devices' - Link = "https://$CIPPUrl/endpoint/MEM/devices?customerId=$($Customer.customerId)" + Link = "https://$CIPPUrl/endpoint/MEM/devices?tenantFilter=$($Customer.defaultDomainName)" Icon = 'fas fa-laptop' }, @{ Name = 'Create User' - Link = "https://$CIPPUrl/identity/administration/users/add?customerId=$($Customer.customerId)" + Link = "https://$CIPPUrl/identity/administration/users/add?tenantFilter=$($Customer.defaultDomainName)" Icon = 'fas fa-user-plus' }, @{ Name = 'Create Group' - Link = "https://$CIPPUrl/identity/administration/groups/add?customerId=73be1f98-1003-4e1a-8e8a-4ffbff7ff2d6" + Link = "https://$CIPPUrl/identity/administration/groups/add?tenantFilter=$($Customer.defaultDomainName)" Icon = 'fas fa-user-group' } ) @@ -1881,7 +1686,7 @@ function Invoke-NinjaOneTenantSync { # Create the Users Card - $TitleLink = "https://$CIPPUrl/identity/administration/users?customerId=$($Customer.customerId)" + $TitleLink = "https://$CIPPUrl/identity/administration/users?tenantFilter=$($Customer.defaultDomainName)" $UsersCardBodyHTML = $UsersEnabledChartHTML + $UsersTypesChartHTML @@ -1963,7 +1768,7 @@ function Invoke-NinjaOneTenantSync { # Create the Devices Card - $TitleLink = "https://$CIPPUrl/endpoint/MEM/devices?customerId=$($Customer.customerId)" + $TitleLink = "https://$CIPPUrl/endpoint/MEM/devices?tenantFilter=$($Customer.defaultDomainName)" $DeviceCardBodyHTML = $DeviceComplianceChartHTML + $DeviceOsChartHTML + $DeviceOnlineChartHTML @@ -1996,7 +1801,7 @@ function Invoke-NinjaOneTenantSync { # Recommended Actions HTML $RecommendedActionsHTML = $Top5Actions | Select-Object 'Recommended Action', @{n = 'Score Impact'; e = { "+$($_.'Score Impact')%" } }, Category, @{n = 'Link'; e = { '' } } | ConvertTo-Html -As Table -Fragment - $TitleLink = "https://security.microsoft.com/securescore?viewid=overview&tid=$($Customer.CustomerId)" + $TitleLink = "https://security.microsoft.com/securescore?viewid=overview&tid=$($Customer.customerId)" $SecureScoreCardBodyHTML = $SecureScoreHTML + [System.Web.HttpUtility]::HtmlDecode($RecommendedActionsHTML) -replace '', '' $SecureScoreCardBodyHTML = $SecureScoreCardBodyHTML -replace '', '' @@ -2012,44 +1817,39 @@ function Invoke-NinjaOneTenantSync { try { $StandardsDefinitions = Get-Content 'config/standards.json' | ConvertFrom-Json -Depth 100 - - $Table = Get-CippTable -tablename 'standards' - - $Filter = "PartitionKey eq 'standards'" - - $AllStandards = (Get-CIPPAzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json -Depth 100 - - $AppliedStandards = ($AllStandards | Where-Object { $_.Tenant -eq $Customer.defaultDomainName -or $_.Tenant -eq 'AllTenants' }) - - $ParsedStandards = foreach ($Standard in $AppliedStandards) { - [PSCustomObject]$Standards = $Standard.Standards - $Standards.PSObject.Properties | ForEach-Object { - $CheckValue = $_ - if ($CheckValue.value) { - $MatchedStandard = $StandardsDefinitions | Where-Object { ($_.name -split 'standards.')[1] -eq $CheckValue.name } - if (($MatchedStandard | Measure-Object).count -eq 1) { - '
  • ' + $($MatchedStandard.label) + ' (' + ($($Standard.Tenant)) + ')
  • ' - } + $AppliedStandards = Get-CIPPStandards -TenantFilter $Customer.defaultDomainName + $Templates = Get-CIPPTable 'templates' + $StandardTemplates = Get-CIPPAzDataTableEntity @Templates | Where-Object { $_.PartitionKey -eq 'StandardsTemplateV2' } + + $ParsedStandards = foreach ($Standard in $AppliedStandards) { + $Template = ($StandardTemplates | Where-Object { $_.RowKey -eq $Standard.TemplateId }).JSON | ConvertFrom-Json + $StandardInfo = $StandardsDefinitions | Where-Object { ($_.name -replace 'standards.', '') -eq $Standard.Standard } + $StandardLabel = $StandardInfo.label + $ParsedActions = foreach ($Action in $Standard.Settings.PSObject.Properties) { + if ($Action.Value -eq $true -and $Action.Name -in @('remediate', 'report', 'alert')) { + (Get-Culture).TextInfo.ToTitleCase($Action.Name) } } - + [PSCustomObject]@{ + Standard = $StandardLabel + Template = $Template.templateName + Actions = $ParsedActions -join ', ' + } } + $ParsedStandardsHTML = $ParsedStandards | ConvertTo-Html -As Table -Fragment + $StandardsTableHTML = '
    ' + (([System.Web.HttpUtility]::HtmlDecode($ParsedStandardsHTML) -replace '', '') -replace '', '') + '
    ' } catch { - $ParsedStandards = 'No standards applied or error retrieving standards' + $StandardsTableHTML = 'No standards applied or error retrieving standards' } - - $TitleLink = "https://$CIPPUrl/tenant/standards/list-applied-standards?customerId=$($Customer.customerId)" - - $CIPPStandardsBodyHTML = '
      ' + $ParsedStandards + '
    ' - - $CIPPStandardsSummaryCardHTML = Get-NinjaOneCard -Title 'CIPP Applied Standards' -Body $CIPPStandardsBodyHTML -Icon 'fas fa-shield-halved' -TitleLink $TitleLink + $TitleLink = "https://$CIPPUrl/tenant/standards/list-standards" + $CIPPStandardsSummaryCardHTML = Get-NinjaOneCard -Title 'CIPP Applied Standards' -Body $StandardsTableHTML -Icon 'fas fa-shield-halved' -TitleLink $TitleLink ### License Card Write-Information 'License Details' $LicenseTableHTML = $LicensesParsed | Sort-Object 'License Name' | ConvertTo-Html -As Table -Fragment $LicenseTableHTML = '
    ' + (([System.Web.HttpUtility]::HtmlDecode($LicenseTableHTML) -replace '', '') -replace '', '') + '
    ' - $TitleLink = "https://$CIPPUrl/tenant/administration/list-licenses?customerId=$($Customer.customerId)" + $TitleLink = "https://$CIPPUrl/tenant/reports/list-licenses?tenantFilter=$($Customer.defaultDomainName)" $LicensesSummaryCardHTML = Get-NinjaOneCard -Title 'Licenses' -Body $LicenseTableHTML -Icon 'fas fa-chart-bar' -TitleLink $TitleLink @@ -2097,7 +1897,7 @@ function Invoke-NinjaOneTenantSync { ) Description = 'Unused Licenses' Colour = $ResultColour - Link = "https://$CIPPUrl/tenant/standards/bpa-report?SearchNow=true&Report=CIPP+Best+Practices+v1.5+-+Tenant+view&tenantFilter=$($Customer.customerId)" + Link = "https://$CIPPUrl/tenant/standards/bpa-report?tenantFilter=$($Customer.defaultDomainName)" }) @@ -2128,7 +1928,7 @@ function Invoke-NinjaOneTenantSync { ) Description = 'Password Never Expires' Colour = $ResultColour - Link = "https://$CIPPUrl/tenant/standards/bpa-report?SearchNow=true&Report=CIPP+Best+Practices+v1.5+-+Tenant+view&tenantFilter=$($Customer.customerId)" + Link = "https://$CIPPUrl/tenant/standards/bpa-report?tenantFilter=$($Customer.defaultDomainName)" }) # oAuth App Consent @@ -2143,7 +1943,7 @@ function Invoke-NinjaOneTenantSync { ) Description = 'OAuth App Consent' Colour = $ResultColour - Link = "https://entra.microsoft.com/$($Customer.customerId)/#view/Microsoft_AAD_IAM/ConsentPoliciesMenuBlade/~/UserSettings" + Link = "https://entra.microsoft.com/$($Customer.defaultDomainName)/#view/Microsoft_AAD_IAM/ConsentPoliciesMenuBlade/~/UserSettings" }) } @@ -2167,7 +1967,7 @@ function Invoke-NinjaOneTenantSync { Value = ($licensedUsers | Measure-Object).count Description = 'Licensed Users' Colour = '#CCCCCC' - Link = "https://$CIPPUrl/identity/administration/users?customerId=$($Customer.customerId)" + Link = "https://$CIPPUrl/identity/administration/users?tenantFilter=$($Customer.defaultDomainName)" }) # Devices @@ -2175,7 +1975,7 @@ function Invoke-NinjaOneTenantSync { Value = ($Devices | Measure-Object).count Description = 'Devices' Colour = '#CCCCCC' - Link = "https://$CIPPUrl/endpoint/MEM/devices?customerId=$($Customer.customerId)" + Link = "https://$CIPPUrl/endpoint/MEM/devices?tenantFilter=$($Customer.defaultDomainName)" }) # Groups @@ -2183,7 +1983,7 @@ function Invoke-NinjaOneTenantSync { Value = ($AllGroups | Measure-Object).count Description = 'Groups' Colour = '#CCCCCC' - Link = "https://$CIPPUrl/identity/administration/groups?customerId=$($Customer.customerId)" + Link = "https://$CIPPUrl/identity/administration/groups?tenantFilter=$($Customer.defaultDomainName)" }) # Roles @@ -2191,7 +1991,7 @@ function Invoke-NinjaOneTenantSync { Value = ($AllRoles | Measure-Object).count Description = 'Roles' Colour = '#CCCCCC' - Link = "https://$CIPPUrl/identity/administration/roles?customerId=$($Customer.customerId)" + Link = "https://$CIPPUrl/identity/administration/roles?tenantFilter=$($Customer.defaultDomainName)" }) @@ -2285,7 +2085,7 @@ function Invoke-NinjaOneTenantSync {
    $($ParsedUsers.count) users found in Tenant
    - Only the first 100 users are displayed here. To see all users please view users in CIPP. + Only the first 100 users are displayed here. To see all users please view users in CIPP.
    @@ -2331,6 +2131,7 @@ function Invoke-NinjaOneTenantSync { } catch { $Message = if ($_.ErrorDetails.Message) { Get-NormalizedError -Message $_.ErrorDetails.Message + Write-Information (Get-CippException -Exception $_ | ConvertTo-Json) } else { $_.Exception.message } From 6f291a4df72138d84755d561bd1693bbc773f864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Wed, 26 Feb 2025 23:39:52 +0100 Subject: [PATCH 087/167] refactor: standardize variable naming and improve logging in API functions License update --- ConversionTable.csv | 126 +++++++++--------- Modules/CIPPCore/Public/ConversionTable.csv | 126 +++++++++--------- .../Invoke-AddConnectionFilter.ps1 | 20 +-- .../Administration/Users/Invoke-AddGuest.ps1 | 50 +++---- Modules/CippExtensions/ConversionTable.csv | 126 +++++++++--------- .../CippExtensions/Public/ConversionTable.csv | 126 +++++++++--------- Tools/Update-LicenseSKUFiles.ps1 | 9 +- 7 files changed, 297 insertions(+), 286 deletions(-) diff --git a/ConversionTable.csv b/ConversionTable.csv index 4463224224a6..e38e1d159430 100644 --- a/ConversionTable.csv +++ b/ConversionTable.csv @@ -228,9 +228,9 @@ Dynamics 365 - Additional Non-Production Instance for Government,CRMTESTINSTANCE Dynamics 365 - Additional Non-Production Instance for Government,CRMTESTINSTANCE_NOPREREQ,2cf302fe-62db-4e20-b573-e0998b1208b5,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 Enterprise Edition - Additional Production Instance for Government,CRMINSTANCE_GCC,2bd3cb20-1bb6-446b-b4d0-089af3a05c52,CRMINSTANCE_GCC,483cc331-f4df-4a3b-b8ca-fe1a247569f6,Microsoft Dynamics CRM Online Instance Dynamics 365 Enterprise Edition - Additional Production Instance for Government,CRMINSTANCE_GCC,2bd3cb20-1bb6-446b-b4d0-089af3a05c52,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization,CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,CRM_AUTO_ROUTING_ENGINE_ADDON,24435e4b-87d0-4d7d-8beb-63a9b1573022,Field Service – Automated Routing Engine Add-On -Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization,CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,CRM_AUTO_ROUTING_ADDON,2ba394e0-6f18-4b77-b45f-a5663bbab540,RETIRED - Field Service – Automated Routing Engine Add-On -Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization,CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization",CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,CRM_AUTO_ROUTING_ENGINE_ADDON,24435e4b-87d0-4d7d-8beb-63a9b1573022,Field Service – Automated Routing Engine Add-On +"Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization",CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,CRM_AUTO_ROUTING_ADDON,2ba394e0-6f18-4b77-b45f-a5663bbab540,RETIRED - Field Service – Automated Routing Engine Add-On +"Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization",CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 Field Service Contractor for Government,D365_FIELD_SERVICE_CONTRACTOR_GOV,e7965e3a-1f49-4d67-a3de-ad1ce460bbcc,CDS_FIELD_SERVICE_CONTRACTOR_GCC,2457fe40-65be-48a1-935f-924ad6e62dba,Common Data Service Field service Part Time Contractors for Government Dynamics 365 Field Service Contractor for Government,D365_FIELD_SERVICE_CONTRACTOR_GOV,e7965e3a-1f49-4d67-a3de-ad1ce460bbcc,EXCHANGE_S_FOUNDATION_GOV,922ba911-5694-4e99-a794-73aed9bfeec8,Exchange Foundation for Government Dynamics 365 Field Service Contractor for Government,D365_FIELD_SERVICE_CONTRACTOR_GOV,e7965e3a-1f49-4d67-a3de-ad1ce460bbcc,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government @@ -253,27 +253,27 @@ Dynamics 365 for Case Management Enterprise Edition,DYN365_ENTERPRISE_CASE_MANAG Dynamics 365 for Case Management Enterprise Edition,DYN365_ENTERPRISE_CASE_MANAGEMENT,d39fb075-21ae-42d0-af80-22a2599749e0,SHAREPOINTENTERPRISE,5dbe027f-2339-4123-9542-606e4d348a72,SharePoint (Plan 2) Dynamics 365 for Case Management Enterprise Edition,DYN365_ENTERPRISE_CASE_MANAGEMENT,d39fb075-21ae-42d0-af80-22a2599749e0,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,Power Apps for Dynamics 365 Dynamics 365 for Case Management Enterprise Edition,DYN365_ENTERPRISE_CASE_MANAGEMENT,d39fb075-21ae-42d0-af80-22a2599749e0,FLOW_DYN_APPS,7e6d7d78-73de-46ba-83b1-6d25117334ba,Power Automate for Dynamics 365 -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,79bb0a8d-e686-4e16-ac59-2b3fd0014a61,Dynamics 365 for Case Management for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,EXCHANGE_S_FOUNDATION_GOV,922ba911-5694-4e99-a794-73aed9bfeec8,Exchange Foundation for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,79bb0a8d-e686-4e16-ac59-2b3fd0014a61,Dynamics 365 for Case Management for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,79bb0a8d-e686-4e16-ac59-2b3fd0014a61,Dynamics 365 for Case Management for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,EXCHANGE_S_FOUNDATION_GOV,922ba911-5694-4e99-a794-73aed9bfeec8,Exchange Foundation for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,79bb0a8d-e686-4e16-ac59-2b3fd0014a61,Dynamics 365 for Case Management for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_CDS_RETAIL,93cc200d-a47f-4c56-aec1-83f8b0d0425a,Common Data Service for Dynamics 365 Retail Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,FLOW_FOR_IOM_USL,9e6d1620-dce9-4655-8933-af8fa5bccc9c,Data Integration for IOM with Power Automate USL Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,CDS_FOR_IOM,2bb89402-51e9-4c5a-be33-e954a9dd1ba6,Dataverse for IOM Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_RETAIL,117e3aa0-8d08-4a19-a6a5-90b7a96e2128,Dynamics 365 Commerce -Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service +Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,"Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service" Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_FP_ACC_PROTECTION,4c00c16c-0304-4421-b598-555c3e78edcb,Dynamics 365 Fraud Protection - Account Protection Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_FP_LOSS_PREVENTION,ecc62904-fa88-4552-a62c-fe582fb31444,Dynamics 365 Fraud Protection - Loss Prevention Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_FP_PURCH_PROTECTION,d703990f-006e-459b-b8dd-1267c4533a22,Dynamics 365 Fraud Protection - Purchase Protection @@ -296,14 +296,14 @@ Dynamics 365 for Customer Service Enterprise Edition,DYN365_ENTERPRISE_CUSTOMER_ Dynamics 365 for Customer Service Enterprise Edition,DYN365_ENTERPRISE_CUSTOMER_SERVICE,749742bf-0d37-4158-a120-33567104deeb,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,POWERAPPS FOR DYNAMICS 365 Dynamics 365 for Customer Service Enterprise Edition,DYN365_ENTERPRISE_CUSTOMER_SERVICE,749742bf-0d37-4158-a120-33567104deeb,SHAREPOINTENTERPRISE,5dbe027f-2339-4123-9542-606e4d348a72,DYNAMICS 365 FOR CUSTOMER SERVICE Dynamics 365 for Customer Service Enterprise Edition,DYN365_ENTERPRISE_CUSTOMER_SERVICE,749742bf-0d37-4158-a120-33567104deeb,SHAREPOINTWAC,e95bec33-7c88-4a70-8e19-b10bd9d0c014,OFFICE ONLINE -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,dc6643d9-1e72-4dce-9f64-1d6eac1f1c5a,Dynamics 365 for Customer Service for Government -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,Forms_Pro_Service_GCC,bb681a9b-58f5-42ee-9926-674325be8aaa,Microsoft Dynamics 365 Customer Voice for Customer Service Enterprise for GCC -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,dc6643d9-1e72-4dce-9f64-1d6eac1f1c5a,Dynamics 365 for Customer Service for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,Forms_Pro_Service_GCC,bb681a9b-58f5-42ee-9926-674325be8aaa,Microsoft Dynamics 365 Customer Voice for Customer Service Enterprise for GCC +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government Dynamics 365 for Field Service Attach to Qualifying Dynamics 365 Base Offer,D365_FIELD_SERVICE_ATTACH,a36cdaa2-a806-4b6e-9ae0-28dbd993c20e,D365_FIELD_SERVICE_ATTACH,55c9148b-d5f0-4101-b5a0-b2727cfc0916,Dynamics 365 for Field Service Attach Dynamics 365 for Field Service Attach to Qualifying Dynamics 365 Base Offer,D365_FIELD_SERVICE_ATTACH,a36cdaa2-a806-4b6e-9ae0-28dbd993c20e,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 for Field Service Enterprise Edition,DYN365_ENTERPRISE_FIELD_SERVICE,c7d15985-e746-4f01-b113-20b575898250,DYN365_ENTERPRISE_FIELD_SERVICE,8c66ef8a-177f-4c0d-853c-d4f219331d09,Dynamics 365 for Field Service @@ -393,13 +393,13 @@ Dynamics 365 for Sales Enterprise Edition,DYN365_ENTERPRISE_SALES,1e1a282c-9c54- Dynamics 365 for Sales Enterprise Edition,DYN365_ENTERPRISE_SALES,1e1a282c-9c54-43a2-9310-98ef728faace,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,PROJECT ONLINE ESSENTIALS Dynamics 365 for Sales Enterprise Edition,DYN365_ENTERPRISE_SALES,1e1a282c-9c54-43a2-9310-98ef728faace,SHAREPOINTENTERPRISE,5dbe027f-2339-4123-9542-606e4d348a72,SHAREPOINT ONLINE (PLAN 2) Dynamics 365 for Sales Enterprise Edition,DYN365_ENTERPRISE_SALES,1e1a282c-9c54-43a2-9310-98ef728faace,SHAREPOINTWAC,e95bec33-7c88-4a70-8e19-b10bd9d0c014,OFFICE ONLINE -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,DYN365_ENTERPRISE_SALES_GOV,213be507-d547-4f79-bc2c-6196bc54c4a3,Dynamics 365 for Sales for Government -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,DYN365_ENTERPRISE_SALES_GOV,213be507-d547-4f79-bc2c-6196bc54c4a3,Dynamics 365 for Sales for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,DYN365_ENTERPRISE_SALES_GOV,213be507-d547-4f79-bc2c-6196bc54c4a3,Dynamics 365 for Sales for Government Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,Forms_Pro_SalesEnt_GCC,33850b82-0a37-4ebb-a0b2-ee163facd716,Microsoft Dynamics 365 Customer Voice for Sales Enterprise for GCC Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User @@ -411,12 +411,12 @@ Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3 Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,DYN365_ENTERPRISE_P1,d56f3deb-50d8-465a-bedb-f079817ccac1,Dynamics 365 Customer Engagement Plan -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,Forms_Pro_Service,67bf4812-f90b-4db9-97e7-c0bbbf7b2d09,Microsoft Dynamics 365 Customer Voice for Customer Service Enterprise -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,Power Apps for Dynamics 365 -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,FLOW_DYN_APPS,7e6d7d78-73de-46ba-83b1-6d25117334ba,Power Automate for Dynamics 365 -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,Project Online Essentials +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,DYN365_ENTERPRISE_P1,d56f3deb-50d8-465a-bedb-f079817ccac1,Dynamics 365 Customer Engagement Plan +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,Forms_Pro_Service,67bf4812-f90b-4db9-97e7-c0bbbf7b2d09,Microsoft Dynamics 365 Customer Voice for Customer Service Enterprise +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,Power Apps for Dynamics 365 +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,FLOW_DYN_APPS,7e6d7d78-73de-46ba-83b1-6d25117334ba,Power Automate for Dynamics 365 +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,Project Online Essentials Dynamics 365 Sales Premium,DYN365_SALES_PREMIUM,2edaa1dc-966d-4475-93d6-8ee8dfd96877,DYN365_SALES_INSIGHTS,fedc185f-0711-4cc0-80ed-0a92da1a8384,Dynamics 365 AI for Sales (Embedded) Dynamics 365 Sales Premium,DYN365_SALES_PREMIUM,2edaa1dc-966d-4475-93d6-8ee8dfd96877,SHAREPOINTENTERPRISE,5dbe027f-2339-4123-9542-606e4d348a72,SharePoint (Plan 2) Dynamics 365 Sales Premium,DYN365_SALES_PREMIUM,2edaa1dc-966d-4475-93d6-8ee8dfd96877,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,Project Online Essentials @@ -432,7 +432,7 @@ Dynamics 365 Sales Premium,DYN365_SALES_PREMIUM,2edaa1dc-966d-4475-93d6-8ee8dfd9 Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,DYN365_CDS_SUPPLYCHAINMANAGEMENT,b6a8b974-2956-4e14-ae81-f0384c363528,Common Data Service for Dynamics 365 Supply Chain Management Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,CDS_FOR_IOM,2bb89402-51e9-4c5a-be33-e954a9dd1ba6,Dataverse for IOM -Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service +Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,"Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service" Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,D365_SCM_Attach,b21c777f-c2d5-486e-88f6-fc0a3e474271,Dynamics 365 for Supply Chain Management Attach Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 for Marketing Business Edition,DYN365_BUSINESS_MARKETING,238e2f8d-e429-4035-94db-6926be4ffe7b,DYN365_BUSINESS_Marketing,393a0c96-9ba1-4af0-8975-fa2f853a25ac,Dynamics 365 Marketing @@ -521,7 +521,7 @@ Dynamics 365 P1 Tria for Information Workers,DYN365_ENTERPRISE_P1_IW,338148b6-1b Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,D365CDSforProjectOperations,7df1d500-ca5c-4229-8cea-815bc88798c9,Common Data Service for Dynamics 365 Project Operations Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,D365_ProjectOperationsCDS,18fa3aba-b085-4105-87d7-55617b8585e6,Dynamics 365 Project Operations CDS Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User -Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service +Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,"Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service" Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,D365_ProjectOperations,69f07c66-bee4-4222-b051-195095efee5b,Dynamics 365 Project Operations Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,Power Apps for Dynamics 365 Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,FLOW_DYN_APPS,7e6d7d78-73de-46ba-83b1-6d25117334ba,Power Automate for Dynamics 365 @@ -4797,18 +4797,18 @@ Power Pages authenticated users T2 min 100 units - 100 users/per site/month capa Power Pages authenticated users T2 min 100 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH,Power_Pages_authenticated_users_T2_min_100_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH,7cae5432-61bb-48c3-b75c-831394ec13a0,PowerPages_Authenticated_Users_GCCH,5410f688-68f2-47a5-9b8f-7466194a806a,Power Pages Authenticated Users per site mthly capacity GCCH New Power Pages authenticated users T2 min 100 units - 100 users/per site/month capacity pack CN_CN,Power Pages authenticated users T2_CN_CN,7d2bb54a-a870-41c2-98d1-1f3b5b523275,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site Power Pages authenticated users T2 min 100 units - 100 users/per site/month capacity pack CN_CN,Power Pages authenticated users T2_CN_CN,7d2bb54a-a870-41c2-98d1-1f3b5b523275,PowerPages_Authenticated_User_CN,967d9574-a076-4bb7-ab89-f41f64bc142e,Power Pages Authenticated Users per site monthly capacity China -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack CN_CN,Power Pages authenticated users T3_CN_CN,2cfd692f-a352-4fa8-b960-e3ad0c9b1178,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack CN_CN,Power Pages authenticated users T3_CN_CN,2cfd692f-a352-4fa8-b960-e3ad0c9b1178,PowerPages_Authenticated_User_CN,967d9574-a076-4bb7-ab89-f41f64bc142e,Power Pages Authenticated Users per site monthly capacity China -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack,878b8bbd-3cd0-4b44-9a56-3406741e65e0,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack,878b8bbd-3cd0-4b44-9a56-3406741e65e0,PowerPages_Authenticated_User,0d3366f3-266e-4117-b422-7cabbc165e7c,Power Pages Authenticated Users per site monthly capacity -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack,878b8bbd-3cd0-4b44-9a56-3406741e65e0,PowerPages_Authenticated_User_GCCH,18e74ca2-b5f0-4802-9a8b-00d2ff1e8322,Power Pages Authenticated Users per site monthly capacity GCCH -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_GCC,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_GCC,53265c61-c78c-4223-ab30-422da0c97fbb,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_GCC,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_GCC,53265c61-c78c-4223-ab30-422da0c97fbb,PowerPages_Authenticated_User_GCC,cdf787bd-1546-48d2-9e93-b21f9ea7067a,Power Pages Authenticated Users per site monthly capacity GCC -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_DOD,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_DOD,398d37b5-8deb-48db-8f7f-703eb2fb7c72,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_DOD,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_DOD,398d37b5-8deb-48db-8f7f-703eb2fb7c72,PowerPages_Authenticated_User_DoD,03300fea-7a88-45a6-b5bd-29653803c591,Power Pages Authenticated Users per site monthly capacity DoD -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH,01d46c34-3525-47d5-bd1a-5f19979938a0,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH,01d46c34-3525-47d5-bd1a-5f19979938a0,PowerPages_Authenticated_User_GCCH,18e74ca2-b5f0-4802-9a8b-00d2ff1e8322,Power Pages Authenticated Users per site monthly capacity GCCH -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH,01d46c34-3525-47d5-bd1a-5f19979938a0,PowerPages_Authenticated_Users_GCCH,5410f688-68f2-47a5-9b8f-7466194a806a,Power Pages Authenticated Users per site mthly capacity GCCH New +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack CN_CN",Power Pages authenticated users T3_CN_CN,2cfd692f-a352-4fa8-b960-e3ad0c9b1178,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack CN_CN",Power Pages authenticated users T3_CN_CN,2cfd692f-a352-4fa8-b960-e3ad0c9b1178,PowerPages_Authenticated_User_CN,967d9574-a076-4bb7-ab89-f41f64bc142e,Power Pages Authenticated Users per site monthly capacity China +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack",878b8bbd-3cd0-4b44-9a56-3406741e65e0,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack",878b8bbd-3cd0-4b44-9a56-3406741e65e0,PowerPages_Authenticated_User,0d3366f3-266e-4117-b422-7cabbc165e7c,Power Pages Authenticated Users per site monthly capacity +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack",878b8bbd-3cd0-4b44-9a56-3406741e65e0,PowerPages_Authenticated_User_GCCH,18e74ca2-b5f0-4802-9a8b-00d2ff1e8322,Power Pages Authenticated Users per site monthly capacity GCCH +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_GCC","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_GCC",53265c61-c78c-4223-ab30-422da0c97fbb,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_GCC","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_GCC",53265c61-c78c-4223-ab30-422da0c97fbb,PowerPages_Authenticated_User_GCC,cdf787bd-1546-48d2-9e93-b21f9ea7067a,Power Pages Authenticated Users per site monthly capacity GCC +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_DOD","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_DOD",398d37b5-8deb-48db-8f7f-703eb2fb7c72,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_DOD","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_DOD",398d37b5-8deb-48db-8f7f-703eb2fb7c72,PowerPages_Authenticated_User_DoD,03300fea-7a88-45a6-b5bd-29653803c591,Power Pages Authenticated Users per site monthly capacity DoD +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH",01d46c34-3525-47d5-bd1a-5f19979938a0,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH",01d46c34-3525-47d5-bd1a-5f19979938a0,PowerPages_Authenticated_User_GCCH,18e74ca2-b5f0-4802-9a8b-00d2ff1e8322,Power Pages Authenticated Users per site monthly capacity GCCH +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH",01d46c34-3525-47d5-bd1a-5f19979938a0,PowerPages_Authenticated_Users_GCCH,5410f688-68f2-47a5-9b8f-7466194a806a,Power Pages Authenticated Users per site mthly capacity GCCH New Power Pages vTrial for Makers,Power_Pages_vTrial_for_Makers,3f9f06f5-3c31-472c-985f-62d9c10ec167,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Power Pages vTrial for Makers,Power_Pages_vTrial_for_Makers,3f9f06f5-3c31-472c-985f-62d9c10ec167,DYN365_CDS_VIRAL,17ab22cd-a0b3-4536-910a-cb6eb12696c0,Common Data Service Power Pages vTrial for Makers,Power_Pages_vTrial_for_Makers,3f9f06f5-3c31-472c-985f-62d9c10ec167,POWER_PAGES_VTRIAL,6817d093-2d30-4249-8bd6-774f01efa78c,Power Pages vTrial for Makers @@ -5146,7 +5146,7 @@ Windows 365 Business 2 vCPU 4 GB 64 GB,CPC_B_2C_4RAM_64GB,42e6818f-8966-444b-b7a Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) -Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,CPC_SS_2,9d2eed2c-b0c0-4a89-940c-bc303444a41b,Windows 365 Business 2 vCPU, 8 GB, 128 GB +Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,CPC_SS_2,9d2eed2c-b0c0-4a89-940c-bc303444a41b,"Windows 365 Business 2 vCPU, 8 GB, 128 GB" Windows 365 Business 2 vCPU 8 GB 256 GB,CPC_B_2C_8RAM_256GB,750d9542-a2f8-41c7-8c81-311352173432,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Windows 365 Business 2 vCPU 8 GB 256 GB,CPC_B_2C_8RAM_256GB,750d9542-a2f8-41c7-8c81-311352173432,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Windows 365 Business 2 vCPU 8 GB 256 GB,CPC_B_2C_8RAM_256GB,750d9542-a2f8-41c7-8c81-311352173432,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) @@ -5177,14 +5177,14 @@ Windows 365 Business 8 vCPU 32 GB 512 GB,CPC_B_8C_32RAM_512GB,8ee402cd-e6a8-4b67 Windows 365 Business 8 vCPU 32 GB 512 GB,CPC_B_8C_32RAM_512GB,8ee402cd-e6a8-4b67-a411-54d1f37a2049,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Windows 365 Business 8 vCPU 32 GB 512 GB,CPC_B_8C_32RAM_512GB,8ee402cd-e6a8-4b67-a411-54d1f37a2049,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) Windows 365 Business 8 vCPU 32 GB 512 GB,CPC_B_8C_32RAM_512GB,8ee402cd-e6a8-4b67-a411-54d1f37a2049,CPC_B_8C_32RAM_512GB,4229a0b4-7f34-4835-b068-6dc8d10be57c,Windows 365 Business 8 vCPU 32 GB 512 GB -Windows 365 Business 16 vCPU, 64 GB, 512 GB,Windows_365_Business_16_vCPU,_64_GB,_512_GB,93d9955a-ec70-44d5-8faa-a194492390f7,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Windows 365 Business 16 vCPU, 64 GB, 512 GB,Windows_365_Business_16_vCPU,_64_GB,_512_GB,93d9955a-ec70-44d5-8faa-a194492390f7,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) -Windows 365 Business 16 vCPU, 64 GB, 512 GB,Windows_365_Business_16_vCPU,_64_GB,_512_GB,93d9955a-ec70-44d5-8faa-a194492390f7,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) -Windows 365 Business 16 vCPU, 64 GB, 512 GB,Windows_365_Business_16_vCPU,_64_GB,_512_GB,93d9955a-ec70-44d5-8faa-a194492390f7,CPC_B_16C_64GB_512GB,cbbedc49-52d5-4fd6-82ac-a5bc51634dc3,Windows 365 Business 16 vCPU, 64 GB, 512 GB -Windows 365 Business 16 vCPU, 64 GB, 1 TB,Windows_365_Business_16_vCPU,_64_GB,_1_TB,24be3cd7-82ca-41a5-94a7-4903373cdcae,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Windows 365 Business 16 vCPU, 64 GB, 1 TB,Windows_365_Business_16_vCPU,_64_GB,_1_TB,24be3cd7-82ca-41a5-94a7-4903373cdcae,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) -Windows 365 Business 16 vCPU, 64 GB, 1 TB,Windows_365_Business_16_vCPU,_64_GB,_1_TB,24be3cd7-82ca-41a5-94a7-4903373cdcae,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) -Windows 365 Business 16 vCPU, 64 GB, 1 TB,Windows_365_Business_16_vCPU,_64_GB,_1_TB,24be3cd7-82ca-41a5-94a7-4903373cdcae,CPC_B_16C_64GB_1TB,37c961db-2cfd-4e13-b81e-b0059ce10e34,Windows 365 Business 16 vCPU, 64 GB, 1 TB +"Windows 365 Business 16 vCPU, 64 GB, 512 GB","Windows_365_Business_16_vCPU,_64_GB,_512_GB",93d9955a-ec70-44d5-8faa-a194492390f7,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Windows 365 Business 16 vCPU, 64 GB, 512 GB","Windows_365_Business_16_vCPU,_64_GB,_512_GB",93d9955a-ec70-44d5-8faa-a194492390f7,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) +"Windows 365 Business 16 vCPU, 64 GB, 512 GB","Windows_365_Business_16_vCPU,_64_GB,_512_GB",93d9955a-ec70-44d5-8faa-a194492390f7,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) +"Windows 365 Business 16 vCPU, 64 GB, 512 GB","Windows_365_Business_16_vCPU,_64_GB,_512_GB",93d9955a-ec70-44d5-8faa-a194492390f7,CPC_B_16C_64GB_512GB,cbbedc49-52d5-4fd6-82ac-a5bc51634dc3,"Windows 365 Business 16 vCPU, 64 GB, 512 GB" +"Windows 365 Business 16 vCPU, 64 GB, 1 TB","Windows_365_Business_16_vCPU,_64_GB,_1_TB",24be3cd7-82ca-41a5-94a7-4903373cdcae,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Windows 365 Business 16 vCPU, 64 GB, 1 TB","Windows_365_Business_16_vCPU,_64_GB,_1_TB",24be3cd7-82ca-41a5-94a7-4903373cdcae,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) +"Windows 365 Business 16 vCPU, 64 GB, 1 TB","Windows_365_Business_16_vCPU,_64_GB,_1_TB",24be3cd7-82ca-41a5-94a7-4903373cdcae,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) +"Windows 365 Business 16 vCPU, 64 GB, 1 TB","Windows_365_Business_16_vCPU,_64_GB,_1_TB",24be3cd7-82ca-41a5-94a7-4903373cdcae,CPC_B_16C_64GB_1TB,37c961db-2cfd-4e13-b81e-b0059ce10e34,"Windows 365 Business 16 vCPU, 64 GB, 1 TB" Windows 365 Enterprise 1 vCPU 2 GB 64 GB,CPC_E_1C_2GB_64GB,0c278af4-c9c1-45de-9f4b-cd929e747a2c,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Windows 365 Enterprise 1 vCPU 2 GB 64 GB,CPC_E_1C_2GB_64GB,0c278af4-c9c1-45de-9f4b-cd929e747a2c,CPC_E_1C_2GB_64GB,86d70dbb-d4c6-4662-ba17-3014204cbb28,Windows 365 Enterprise 1 vCPU 2 GB 64 GB Windows 365 Enterprise 2 vCPU 4 GB 64 GB,CPC_E_2C_4GB_64GB,7bb14422-3b90-4389-a7be-f1b745fc037f,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation diff --git a/Modules/CIPPCore/Public/ConversionTable.csv b/Modules/CIPPCore/Public/ConversionTable.csv index 4463224224a6..e38e1d159430 100644 --- a/Modules/CIPPCore/Public/ConversionTable.csv +++ b/Modules/CIPPCore/Public/ConversionTable.csv @@ -228,9 +228,9 @@ Dynamics 365 - Additional Non-Production Instance for Government,CRMTESTINSTANCE Dynamics 365 - Additional Non-Production Instance for Government,CRMTESTINSTANCE_NOPREREQ,2cf302fe-62db-4e20-b573-e0998b1208b5,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 Enterprise Edition - Additional Production Instance for Government,CRMINSTANCE_GCC,2bd3cb20-1bb6-446b-b4d0-089af3a05c52,CRMINSTANCE_GCC,483cc331-f4df-4a3b-b8ca-fe1a247569f6,Microsoft Dynamics CRM Online Instance Dynamics 365 Enterprise Edition - Additional Production Instance for Government,CRMINSTANCE_GCC,2bd3cb20-1bb6-446b-b4d0-089af3a05c52,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization,CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,CRM_AUTO_ROUTING_ENGINE_ADDON,24435e4b-87d0-4d7d-8beb-63a9b1573022,Field Service – Automated Routing Engine Add-On -Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization,CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,CRM_AUTO_ROUTING_ADDON,2ba394e0-6f18-4b77-b45f-a5663bbab540,RETIRED - Field Service – Automated Routing Engine Add-On -Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization,CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization",CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,CRM_AUTO_ROUTING_ENGINE_ADDON,24435e4b-87d0-4d7d-8beb-63a9b1573022,Field Service – Automated Routing Engine Add-On +"Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization",CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,CRM_AUTO_ROUTING_ADDON,2ba394e0-6f18-4b77-b45f-a5663bbab540,RETIRED - Field Service – Automated Routing Engine Add-On +"Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization",CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 Field Service Contractor for Government,D365_FIELD_SERVICE_CONTRACTOR_GOV,e7965e3a-1f49-4d67-a3de-ad1ce460bbcc,CDS_FIELD_SERVICE_CONTRACTOR_GCC,2457fe40-65be-48a1-935f-924ad6e62dba,Common Data Service Field service Part Time Contractors for Government Dynamics 365 Field Service Contractor for Government,D365_FIELD_SERVICE_CONTRACTOR_GOV,e7965e3a-1f49-4d67-a3de-ad1ce460bbcc,EXCHANGE_S_FOUNDATION_GOV,922ba911-5694-4e99-a794-73aed9bfeec8,Exchange Foundation for Government Dynamics 365 Field Service Contractor for Government,D365_FIELD_SERVICE_CONTRACTOR_GOV,e7965e3a-1f49-4d67-a3de-ad1ce460bbcc,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government @@ -253,27 +253,27 @@ Dynamics 365 for Case Management Enterprise Edition,DYN365_ENTERPRISE_CASE_MANAG Dynamics 365 for Case Management Enterprise Edition,DYN365_ENTERPRISE_CASE_MANAGEMENT,d39fb075-21ae-42d0-af80-22a2599749e0,SHAREPOINTENTERPRISE,5dbe027f-2339-4123-9542-606e4d348a72,SharePoint (Plan 2) Dynamics 365 for Case Management Enterprise Edition,DYN365_ENTERPRISE_CASE_MANAGEMENT,d39fb075-21ae-42d0-af80-22a2599749e0,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,Power Apps for Dynamics 365 Dynamics 365 for Case Management Enterprise Edition,DYN365_ENTERPRISE_CASE_MANAGEMENT,d39fb075-21ae-42d0-af80-22a2599749e0,FLOW_DYN_APPS,7e6d7d78-73de-46ba-83b1-6d25117334ba,Power Automate for Dynamics 365 -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,79bb0a8d-e686-4e16-ac59-2b3fd0014a61,Dynamics 365 for Case Management for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,EXCHANGE_S_FOUNDATION_GOV,922ba911-5694-4e99-a794-73aed9bfeec8,Exchange Foundation for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,79bb0a8d-e686-4e16-ac59-2b3fd0014a61,Dynamics 365 for Case Management for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,79bb0a8d-e686-4e16-ac59-2b3fd0014a61,Dynamics 365 for Case Management for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,EXCHANGE_S_FOUNDATION_GOV,922ba911-5694-4e99-a794-73aed9bfeec8,Exchange Foundation for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,79bb0a8d-e686-4e16-ac59-2b3fd0014a61,Dynamics 365 for Case Management for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_CDS_RETAIL,93cc200d-a47f-4c56-aec1-83f8b0d0425a,Common Data Service for Dynamics 365 Retail Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,FLOW_FOR_IOM_USL,9e6d1620-dce9-4655-8933-af8fa5bccc9c,Data Integration for IOM with Power Automate USL Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,CDS_FOR_IOM,2bb89402-51e9-4c5a-be33-e954a9dd1ba6,Dataverse for IOM Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_RETAIL,117e3aa0-8d08-4a19-a6a5-90b7a96e2128,Dynamics 365 Commerce -Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service +Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,"Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service" Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_FP_ACC_PROTECTION,4c00c16c-0304-4421-b598-555c3e78edcb,Dynamics 365 Fraud Protection - Account Protection Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_FP_LOSS_PREVENTION,ecc62904-fa88-4552-a62c-fe582fb31444,Dynamics 365 Fraud Protection - Loss Prevention Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_FP_PURCH_PROTECTION,d703990f-006e-459b-b8dd-1267c4533a22,Dynamics 365 Fraud Protection - Purchase Protection @@ -296,14 +296,14 @@ Dynamics 365 for Customer Service Enterprise Edition,DYN365_ENTERPRISE_CUSTOMER_ Dynamics 365 for Customer Service Enterprise Edition,DYN365_ENTERPRISE_CUSTOMER_SERVICE,749742bf-0d37-4158-a120-33567104deeb,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,POWERAPPS FOR DYNAMICS 365 Dynamics 365 for Customer Service Enterprise Edition,DYN365_ENTERPRISE_CUSTOMER_SERVICE,749742bf-0d37-4158-a120-33567104deeb,SHAREPOINTENTERPRISE,5dbe027f-2339-4123-9542-606e4d348a72,DYNAMICS 365 FOR CUSTOMER SERVICE Dynamics 365 for Customer Service Enterprise Edition,DYN365_ENTERPRISE_CUSTOMER_SERVICE,749742bf-0d37-4158-a120-33567104deeb,SHAREPOINTWAC,e95bec33-7c88-4a70-8e19-b10bd9d0c014,OFFICE ONLINE -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,dc6643d9-1e72-4dce-9f64-1d6eac1f1c5a,Dynamics 365 for Customer Service for Government -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,Forms_Pro_Service_GCC,bb681a9b-58f5-42ee-9926-674325be8aaa,Microsoft Dynamics 365 Customer Voice for Customer Service Enterprise for GCC -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,dc6643d9-1e72-4dce-9f64-1d6eac1f1c5a,Dynamics 365 for Customer Service for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,Forms_Pro_Service_GCC,bb681a9b-58f5-42ee-9926-674325be8aaa,Microsoft Dynamics 365 Customer Voice for Customer Service Enterprise for GCC +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government Dynamics 365 for Field Service Attach to Qualifying Dynamics 365 Base Offer,D365_FIELD_SERVICE_ATTACH,a36cdaa2-a806-4b6e-9ae0-28dbd993c20e,D365_FIELD_SERVICE_ATTACH,55c9148b-d5f0-4101-b5a0-b2727cfc0916,Dynamics 365 for Field Service Attach Dynamics 365 for Field Service Attach to Qualifying Dynamics 365 Base Offer,D365_FIELD_SERVICE_ATTACH,a36cdaa2-a806-4b6e-9ae0-28dbd993c20e,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 for Field Service Enterprise Edition,DYN365_ENTERPRISE_FIELD_SERVICE,c7d15985-e746-4f01-b113-20b575898250,DYN365_ENTERPRISE_FIELD_SERVICE,8c66ef8a-177f-4c0d-853c-d4f219331d09,Dynamics 365 for Field Service @@ -393,13 +393,13 @@ Dynamics 365 for Sales Enterprise Edition,DYN365_ENTERPRISE_SALES,1e1a282c-9c54- Dynamics 365 for Sales Enterprise Edition,DYN365_ENTERPRISE_SALES,1e1a282c-9c54-43a2-9310-98ef728faace,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,PROJECT ONLINE ESSENTIALS Dynamics 365 for Sales Enterprise Edition,DYN365_ENTERPRISE_SALES,1e1a282c-9c54-43a2-9310-98ef728faace,SHAREPOINTENTERPRISE,5dbe027f-2339-4123-9542-606e4d348a72,SHAREPOINT ONLINE (PLAN 2) Dynamics 365 for Sales Enterprise Edition,DYN365_ENTERPRISE_SALES,1e1a282c-9c54-43a2-9310-98ef728faace,SHAREPOINTWAC,e95bec33-7c88-4a70-8e19-b10bd9d0c014,OFFICE ONLINE -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,DYN365_ENTERPRISE_SALES_GOV,213be507-d547-4f79-bc2c-6196bc54c4a3,Dynamics 365 for Sales for Government -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,DYN365_ENTERPRISE_SALES_GOV,213be507-d547-4f79-bc2c-6196bc54c4a3,Dynamics 365 for Sales for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,DYN365_ENTERPRISE_SALES_GOV,213be507-d547-4f79-bc2c-6196bc54c4a3,Dynamics 365 for Sales for Government Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,Forms_Pro_SalesEnt_GCC,33850b82-0a37-4ebb-a0b2-ee163facd716,Microsoft Dynamics 365 Customer Voice for Sales Enterprise for GCC Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User @@ -411,12 +411,12 @@ Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3 Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,DYN365_ENTERPRISE_P1,d56f3deb-50d8-465a-bedb-f079817ccac1,Dynamics 365 Customer Engagement Plan -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,Forms_Pro_Service,67bf4812-f90b-4db9-97e7-c0bbbf7b2d09,Microsoft Dynamics 365 Customer Voice for Customer Service Enterprise -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,Power Apps for Dynamics 365 -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,FLOW_DYN_APPS,7e6d7d78-73de-46ba-83b1-6d25117334ba,Power Automate for Dynamics 365 -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,Project Online Essentials +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,DYN365_ENTERPRISE_P1,d56f3deb-50d8-465a-bedb-f079817ccac1,Dynamics 365 Customer Engagement Plan +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,Forms_Pro_Service,67bf4812-f90b-4db9-97e7-c0bbbf7b2d09,Microsoft Dynamics 365 Customer Voice for Customer Service Enterprise +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,Power Apps for Dynamics 365 +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,FLOW_DYN_APPS,7e6d7d78-73de-46ba-83b1-6d25117334ba,Power Automate for Dynamics 365 +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,Project Online Essentials Dynamics 365 Sales Premium,DYN365_SALES_PREMIUM,2edaa1dc-966d-4475-93d6-8ee8dfd96877,DYN365_SALES_INSIGHTS,fedc185f-0711-4cc0-80ed-0a92da1a8384,Dynamics 365 AI for Sales (Embedded) Dynamics 365 Sales Premium,DYN365_SALES_PREMIUM,2edaa1dc-966d-4475-93d6-8ee8dfd96877,SHAREPOINTENTERPRISE,5dbe027f-2339-4123-9542-606e4d348a72,SharePoint (Plan 2) Dynamics 365 Sales Premium,DYN365_SALES_PREMIUM,2edaa1dc-966d-4475-93d6-8ee8dfd96877,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,Project Online Essentials @@ -432,7 +432,7 @@ Dynamics 365 Sales Premium,DYN365_SALES_PREMIUM,2edaa1dc-966d-4475-93d6-8ee8dfd9 Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,DYN365_CDS_SUPPLYCHAINMANAGEMENT,b6a8b974-2956-4e14-ae81-f0384c363528,Common Data Service for Dynamics 365 Supply Chain Management Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,CDS_FOR_IOM,2bb89402-51e9-4c5a-be33-e954a9dd1ba6,Dataverse for IOM -Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service +Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,"Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service" Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,D365_SCM_Attach,b21c777f-c2d5-486e-88f6-fc0a3e474271,Dynamics 365 for Supply Chain Management Attach Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 for Marketing Business Edition,DYN365_BUSINESS_MARKETING,238e2f8d-e429-4035-94db-6926be4ffe7b,DYN365_BUSINESS_Marketing,393a0c96-9ba1-4af0-8975-fa2f853a25ac,Dynamics 365 Marketing @@ -521,7 +521,7 @@ Dynamics 365 P1 Tria for Information Workers,DYN365_ENTERPRISE_P1_IW,338148b6-1b Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,D365CDSforProjectOperations,7df1d500-ca5c-4229-8cea-815bc88798c9,Common Data Service for Dynamics 365 Project Operations Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,D365_ProjectOperationsCDS,18fa3aba-b085-4105-87d7-55617b8585e6,Dynamics 365 Project Operations CDS Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User -Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service +Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,"Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service" Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,D365_ProjectOperations,69f07c66-bee4-4222-b051-195095efee5b,Dynamics 365 Project Operations Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,Power Apps for Dynamics 365 Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,FLOW_DYN_APPS,7e6d7d78-73de-46ba-83b1-6d25117334ba,Power Automate for Dynamics 365 @@ -4797,18 +4797,18 @@ Power Pages authenticated users T2 min 100 units - 100 users/per site/month capa Power Pages authenticated users T2 min 100 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH,Power_Pages_authenticated_users_T2_min_100_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH,7cae5432-61bb-48c3-b75c-831394ec13a0,PowerPages_Authenticated_Users_GCCH,5410f688-68f2-47a5-9b8f-7466194a806a,Power Pages Authenticated Users per site mthly capacity GCCH New Power Pages authenticated users T2 min 100 units - 100 users/per site/month capacity pack CN_CN,Power Pages authenticated users T2_CN_CN,7d2bb54a-a870-41c2-98d1-1f3b5b523275,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site Power Pages authenticated users T2 min 100 units - 100 users/per site/month capacity pack CN_CN,Power Pages authenticated users T2_CN_CN,7d2bb54a-a870-41c2-98d1-1f3b5b523275,PowerPages_Authenticated_User_CN,967d9574-a076-4bb7-ab89-f41f64bc142e,Power Pages Authenticated Users per site monthly capacity China -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack CN_CN,Power Pages authenticated users T3_CN_CN,2cfd692f-a352-4fa8-b960-e3ad0c9b1178,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack CN_CN,Power Pages authenticated users T3_CN_CN,2cfd692f-a352-4fa8-b960-e3ad0c9b1178,PowerPages_Authenticated_User_CN,967d9574-a076-4bb7-ab89-f41f64bc142e,Power Pages Authenticated Users per site monthly capacity China -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack,878b8bbd-3cd0-4b44-9a56-3406741e65e0,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack,878b8bbd-3cd0-4b44-9a56-3406741e65e0,PowerPages_Authenticated_User,0d3366f3-266e-4117-b422-7cabbc165e7c,Power Pages Authenticated Users per site monthly capacity -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack,878b8bbd-3cd0-4b44-9a56-3406741e65e0,PowerPages_Authenticated_User_GCCH,18e74ca2-b5f0-4802-9a8b-00d2ff1e8322,Power Pages Authenticated Users per site monthly capacity GCCH -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_GCC,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_GCC,53265c61-c78c-4223-ab30-422da0c97fbb,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_GCC,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_GCC,53265c61-c78c-4223-ab30-422da0c97fbb,PowerPages_Authenticated_User_GCC,cdf787bd-1546-48d2-9e93-b21f9ea7067a,Power Pages Authenticated Users per site monthly capacity GCC -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_DOD,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_DOD,398d37b5-8deb-48db-8f7f-703eb2fb7c72,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_DOD,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_DOD,398d37b5-8deb-48db-8f7f-703eb2fb7c72,PowerPages_Authenticated_User_DoD,03300fea-7a88-45a6-b5bd-29653803c591,Power Pages Authenticated Users per site monthly capacity DoD -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH,01d46c34-3525-47d5-bd1a-5f19979938a0,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH,01d46c34-3525-47d5-bd1a-5f19979938a0,PowerPages_Authenticated_User_GCCH,18e74ca2-b5f0-4802-9a8b-00d2ff1e8322,Power Pages Authenticated Users per site monthly capacity GCCH -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH,01d46c34-3525-47d5-bd1a-5f19979938a0,PowerPages_Authenticated_Users_GCCH,5410f688-68f2-47a5-9b8f-7466194a806a,Power Pages Authenticated Users per site mthly capacity GCCH New +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack CN_CN",Power Pages authenticated users T3_CN_CN,2cfd692f-a352-4fa8-b960-e3ad0c9b1178,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack CN_CN",Power Pages authenticated users T3_CN_CN,2cfd692f-a352-4fa8-b960-e3ad0c9b1178,PowerPages_Authenticated_User_CN,967d9574-a076-4bb7-ab89-f41f64bc142e,Power Pages Authenticated Users per site monthly capacity China +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack",878b8bbd-3cd0-4b44-9a56-3406741e65e0,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack",878b8bbd-3cd0-4b44-9a56-3406741e65e0,PowerPages_Authenticated_User,0d3366f3-266e-4117-b422-7cabbc165e7c,Power Pages Authenticated Users per site monthly capacity +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack",878b8bbd-3cd0-4b44-9a56-3406741e65e0,PowerPages_Authenticated_User_GCCH,18e74ca2-b5f0-4802-9a8b-00d2ff1e8322,Power Pages Authenticated Users per site monthly capacity GCCH +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_GCC","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_GCC",53265c61-c78c-4223-ab30-422da0c97fbb,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_GCC","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_GCC",53265c61-c78c-4223-ab30-422da0c97fbb,PowerPages_Authenticated_User_GCC,cdf787bd-1546-48d2-9e93-b21f9ea7067a,Power Pages Authenticated Users per site monthly capacity GCC +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_DOD","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_DOD",398d37b5-8deb-48db-8f7f-703eb2fb7c72,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_DOD","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_DOD",398d37b5-8deb-48db-8f7f-703eb2fb7c72,PowerPages_Authenticated_User_DoD,03300fea-7a88-45a6-b5bd-29653803c591,Power Pages Authenticated Users per site monthly capacity DoD +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH",01d46c34-3525-47d5-bd1a-5f19979938a0,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH",01d46c34-3525-47d5-bd1a-5f19979938a0,PowerPages_Authenticated_User_GCCH,18e74ca2-b5f0-4802-9a8b-00d2ff1e8322,Power Pages Authenticated Users per site monthly capacity GCCH +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH",01d46c34-3525-47d5-bd1a-5f19979938a0,PowerPages_Authenticated_Users_GCCH,5410f688-68f2-47a5-9b8f-7466194a806a,Power Pages Authenticated Users per site mthly capacity GCCH New Power Pages vTrial for Makers,Power_Pages_vTrial_for_Makers,3f9f06f5-3c31-472c-985f-62d9c10ec167,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Power Pages vTrial for Makers,Power_Pages_vTrial_for_Makers,3f9f06f5-3c31-472c-985f-62d9c10ec167,DYN365_CDS_VIRAL,17ab22cd-a0b3-4536-910a-cb6eb12696c0,Common Data Service Power Pages vTrial for Makers,Power_Pages_vTrial_for_Makers,3f9f06f5-3c31-472c-985f-62d9c10ec167,POWER_PAGES_VTRIAL,6817d093-2d30-4249-8bd6-774f01efa78c,Power Pages vTrial for Makers @@ -5146,7 +5146,7 @@ Windows 365 Business 2 vCPU 4 GB 64 GB,CPC_B_2C_4RAM_64GB,42e6818f-8966-444b-b7a Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) -Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,CPC_SS_2,9d2eed2c-b0c0-4a89-940c-bc303444a41b,Windows 365 Business 2 vCPU, 8 GB, 128 GB +Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,CPC_SS_2,9d2eed2c-b0c0-4a89-940c-bc303444a41b,"Windows 365 Business 2 vCPU, 8 GB, 128 GB" Windows 365 Business 2 vCPU 8 GB 256 GB,CPC_B_2C_8RAM_256GB,750d9542-a2f8-41c7-8c81-311352173432,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Windows 365 Business 2 vCPU 8 GB 256 GB,CPC_B_2C_8RAM_256GB,750d9542-a2f8-41c7-8c81-311352173432,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Windows 365 Business 2 vCPU 8 GB 256 GB,CPC_B_2C_8RAM_256GB,750d9542-a2f8-41c7-8c81-311352173432,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) @@ -5177,14 +5177,14 @@ Windows 365 Business 8 vCPU 32 GB 512 GB,CPC_B_8C_32RAM_512GB,8ee402cd-e6a8-4b67 Windows 365 Business 8 vCPU 32 GB 512 GB,CPC_B_8C_32RAM_512GB,8ee402cd-e6a8-4b67-a411-54d1f37a2049,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Windows 365 Business 8 vCPU 32 GB 512 GB,CPC_B_8C_32RAM_512GB,8ee402cd-e6a8-4b67-a411-54d1f37a2049,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) Windows 365 Business 8 vCPU 32 GB 512 GB,CPC_B_8C_32RAM_512GB,8ee402cd-e6a8-4b67-a411-54d1f37a2049,CPC_B_8C_32RAM_512GB,4229a0b4-7f34-4835-b068-6dc8d10be57c,Windows 365 Business 8 vCPU 32 GB 512 GB -Windows 365 Business 16 vCPU, 64 GB, 512 GB,Windows_365_Business_16_vCPU,_64_GB,_512_GB,93d9955a-ec70-44d5-8faa-a194492390f7,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Windows 365 Business 16 vCPU, 64 GB, 512 GB,Windows_365_Business_16_vCPU,_64_GB,_512_GB,93d9955a-ec70-44d5-8faa-a194492390f7,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) -Windows 365 Business 16 vCPU, 64 GB, 512 GB,Windows_365_Business_16_vCPU,_64_GB,_512_GB,93d9955a-ec70-44d5-8faa-a194492390f7,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) -Windows 365 Business 16 vCPU, 64 GB, 512 GB,Windows_365_Business_16_vCPU,_64_GB,_512_GB,93d9955a-ec70-44d5-8faa-a194492390f7,CPC_B_16C_64GB_512GB,cbbedc49-52d5-4fd6-82ac-a5bc51634dc3,Windows 365 Business 16 vCPU, 64 GB, 512 GB -Windows 365 Business 16 vCPU, 64 GB, 1 TB,Windows_365_Business_16_vCPU,_64_GB,_1_TB,24be3cd7-82ca-41a5-94a7-4903373cdcae,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Windows 365 Business 16 vCPU, 64 GB, 1 TB,Windows_365_Business_16_vCPU,_64_GB,_1_TB,24be3cd7-82ca-41a5-94a7-4903373cdcae,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) -Windows 365 Business 16 vCPU, 64 GB, 1 TB,Windows_365_Business_16_vCPU,_64_GB,_1_TB,24be3cd7-82ca-41a5-94a7-4903373cdcae,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) -Windows 365 Business 16 vCPU, 64 GB, 1 TB,Windows_365_Business_16_vCPU,_64_GB,_1_TB,24be3cd7-82ca-41a5-94a7-4903373cdcae,CPC_B_16C_64GB_1TB,37c961db-2cfd-4e13-b81e-b0059ce10e34,Windows 365 Business 16 vCPU, 64 GB, 1 TB +"Windows 365 Business 16 vCPU, 64 GB, 512 GB","Windows_365_Business_16_vCPU,_64_GB,_512_GB",93d9955a-ec70-44d5-8faa-a194492390f7,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Windows 365 Business 16 vCPU, 64 GB, 512 GB","Windows_365_Business_16_vCPU,_64_GB,_512_GB",93d9955a-ec70-44d5-8faa-a194492390f7,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) +"Windows 365 Business 16 vCPU, 64 GB, 512 GB","Windows_365_Business_16_vCPU,_64_GB,_512_GB",93d9955a-ec70-44d5-8faa-a194492390f7,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) +"Windows 365 Business 16 vCPU, 64 GB, 512 GB","Windows_365_Business_16_vCPU,_64_GB,_512_GB",93d9955a-ec70-44d5-8faa-a194492390f7,CPC_B_16C_64GB_512GB,cbbedc49-52d5-4fd6-82ac-a5bc51634dc3,"Windows 365 Business 16 vCPU, 64 GB, 512 GB" +"Windows 365 Business 16 vCPU, 64 GB, 1 TB","Windows_365_Business_16_vCPU,_64_GB,_1_TB",24be3cd7-82ca-41a5-94a7-4903373cdcae,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Windows 365 Business 16 vCPU, 64 GB, 1 TB","Windows_365_Business_16_vCPU,_64_GB,_1_TB",24be3cd7-82ca-41a5-94a7-4903373cdcae,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) +"Windows 365 Business 16 vCPU, 64 GB, 1 TB","Windows_365_Business_16_vCPU,_64_GB,_1_TB",24be3cd7-82ca-41a5-94a7-4903373cdcae,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) +"Windows 365 Business 16 vCPU, 64 GB, 1 TB","Windows_365_Business_16_vCPU,_64_GB,_1_TB",24be3cd7-82ca-41a5-94a7-4903373cdcae,CPC_B_16C_64GB_1TB,37c961db-2cfd-4e13-b81e-b0059ce10e34,"Windows 365 Business 16 vCPU, 64 GB, 1 TB" Windows 365 Enterprise 1 vCPU 2 GB 64 GB,CPC_E_1C_2GB_64GB,0c278af4-c9c1-45de-9f4b-cd929e747a2c,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Windows 365 Enterprise 1 vCPU 2 GB 64 GB,CPC_E_1C_2GB_64GB,0c278af4-c9c1-45de-9f4b-cd929e747a2c,CPC_E_1C_2GB_64GB,86d70dbb-d4c6-4662-ba17-3014204cbb28,Windows 365 Enterprise 1 vCPU 2 GB 64 GB Windows 365 Enterprise 2 vCPU 4 GB 64 GB,CPC_E_2C_4GB_64GB,7bb14422-3b90-4389-a7be-f1b745fc037f,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddConnectionFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddConnectionFilter.ps1 index 51ea0dcc4908..366ddbc8132c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddConnectionFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddConnectionFilter.ps1 @@ -12,21 +12,23 @@ Function Invoke-AddConnectionFilter { $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' $RequestParams = $Request.Body.PowerShellCommand | - ConvertFrom-Json | - Select-Object -Property *, @{Name='identity'; Expression={$_.name}} -ExcludeProperty GUID, comments, name + ConvertFrom-Json | + Select-Object -Property *, @{Name = 'identity'; Expression = { $_.name } } -ExcludeProperty GUID, comments, name $Tenants = ($Request.body.selectedTenants).value - $Result = foreach ($Tenantfilter in $tenants) { + $Result = foreach ($TenantFilter in $Tenants) { try { - $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet 'Set-HostedConnectionFilterPolicy' -cmdParams $RequestParams - "Successfully created Connectionfilter for $tenantfilter." - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $tenantfilter -message "Updated Connection filter rule for $($tenantfilter)" -sev Info + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Set-HostedConnectionFilterPolicy' -cmdParams $RequestParams + "Successfully created Connection filter for $TenantFilter." + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message "Updated Connection filter rule for $($TenantFilter)" -sev Info } catch { - "Could not create create Connection Filter rule for $($tenantfilter): $($_.Exception.message)" - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $tenantfilter -message "Could not create create connection filter rule for $($tenantfilter): $($_.Exception.message)" -sev Error + $ErrorMessage = Get-CippException -Exception $_ + "Failed to create Connection Filter rule for $($TenantFilter): $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message "Failed to create connection filter rule for $($TenantFilter): $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage } } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddGuest.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddGuest.ps1 index 31cae1bd1f10..d84dd6bc8bcb 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddGuest.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddGuest.ps1 @@ -11,47 +11,51 @@ Function Invoke-AddGuest { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + $TenantFilter = $Request.Body.tenantFilter $Results = [System.Collections.ArrayList]@() - $userobj = $Request.body - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + $UserObject = $Request.Body try { - if ($userobj.RedirectURL) { + if ($UserObject.RedirectURL) { $BodyToship = [pscustomobject] @{ - 'InvitedUserDisplayName' = $userobj.Displayname - 'InvitedUserEmailAddress' = $($userobj.mail) - 'inviteRedirectUrl' = $($userobj.RedirectURL) - 'sendInvitationMessage' = [boolean]$userobj.SendInvite + 'InvitedUserDisplayName' = $UserObject.DisplayName + 'InvitedUserEmailAddress' = $($UserObject.mail) + 'inviteRedirectUrl' = $($UserObject.RedirectURL) + 'sendInvitationMessage' = [bool]$UserObject.SendInvite } } else { $BodyToship = [pscustomobject] @{ - 'InvitedUserDisplayName' = $userobj.Displayname - 'InvitedUserEmailAddress' = $($userobj.mail) - 'sendInvitationMessage' = [boolean]$userobj.SendInvite + 'InvitedUserDisplayName' = $UserObject.DisplayName + 'InvitedUserEmailAddress' = $($UserObject.mail) + 'sendInvitationMessage' = [bool]$UserObject.SendInvite 'inviteRedirectUrl' = 'https://myapps.microsoft.com' } } $bodyToShip = ConvertTo-Json -Depth 10 -InputObject $BodyToship -Compress - $GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/invitations' -tenantid $Userobj.tenantFilter -type POST -body $BodyToship -verbose - if ($Userobj.sendInvite -eq 'true') { - $results.add('Invited Guest. Invite Email sent') - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($userobj.tenantFilter) -message "Invited Guest $($userobj.displayname) with Email Invite " -Sev 'Info' + $null = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/invitations' -tenantid $TenantFilter -type POST -body $BodyToship -verbose + if ($UserObject.SendInvite -eq $true) { + $Results.Add('Invited Guest. Invite Email sent') + Write-LogMessage -headers $Headers -API $APIName -tenant $($TenantFilter) -message "Invited Guest $($UserObject.DisplayName) with Email Invite " -Sev 'Info' } else { - $results.add('Invited Guest. No Invite Email was sent') - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($userobj.tenantFilter) -message "Invited Guest $($userobj.displayname) with no Email Invite " -Sev 'Info' + $Results.Add('Invited Guest. No Invite Email was sent') + Write-LogMessage -headers $Headers -API $APIName -tenant $($TenantFilter) -message "Invited Guest $($UserObject.DisplayName) with no Email Invite " -Sev 'Info' } + $StatusCode = [HttpStatusCode]::OK } catch { - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($userobj.tenantFilter) -message "Guest Invite API failed. $($_.Exception.Message)" -Sev 'Error' - $body = $results.add("Failed to Invite Guest. $($_.Exception.Message)" ) + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed to Invite Guest. $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $($TenantFilter) -message $Result -Sev 'Error' -LogData $ErrorMessage + $Results.Add($Result) + $StatusCode = [HttpStatusCode]::BadRequest } - $body = @{'Results' = @($results) } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Body + StatusCode = $StatusCode + Body = @{Results = @($Results) } }) } diff --git a/Modules/CippExtensions/ConversionTable.csv b/Modules/CippExtensions/ConversionTable.csv index 4463224224a6..e38e1d159430 100644 --- a/Modules/CippExtensions/ConversionTable.csv +++ b/Modules/CippExtensions/ConversionTable.csv @@ -228,9 +228,9 @@ Dynamics 365 - Additional Non-Production Instance for Government,CRMTESTINSTANCE Dynamics 365 - Additional Non-Production Instance for Government,CRMTESTINSTANCE_NOPREREQ,2cf302fe-62db-4e20-b573-e0998b1208b5,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 Enterprise Edition - Additional Production Instance for Government,CRMINSTANCE_GCC,2bd3cb20-1bb6-446b-b4d0-089af3a05c52,CRMINSTANCE_GCC,483cc331-f4df-4a3b-b8ca-fe1a247569f6,Microsoft Dynamics CRM Online Instance Dynamics 365 Enterprise Edition - Additional Production Instance for Government,CRMINSTANCE_GCC,2bd3cb20-1bb6-446b-b4d0-089af3a05c52,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization,CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,CRM_AUTO_ROUTING_ENGINE_ADDON,24435e4b-87d0-4d7d-8beb-63a9b1573022,Field Service – Automated Routing Engine Add-On -Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization,CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,CRM_AUTO_ROUTING_ADDON,2ba394e0-6f18-4b77-b45f-a5663bbab540,RETIRED - Field Service – Automated Routing Engine Add-On -Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization,CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization",CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,CRM_AUTO_ROUTING_ENGINE_ADDON,24435e4b-87d0-4d7d-8beb-63a9b1573022,Field Service – Automated Routing Engine Add-On +"Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization",CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,CRM_AUTO_ROUTING_ADDON,2ba394e0-6f18-4b77-b45f-a5663bbab540,RETIRED - Field Service – Automated Routing Engine Add-On +"Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization",CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 Field Service Contractor for Government,D365_FIELD_SERVICE_CONTRACTOR_GOV,e7965e3a-1f49-4d67-a3de-ad1ce460bbcc,CDS_FIELD_SERVICE_CONTRACTOR_GCC,2457fe40-65be-48a1-935f-924ad6e62dba,Common Data Service Field service Part Time Contractors for Government Dynamics 365 Field Service Contractor for Government,D365_FIELD_SERVICE_CONTRACTOR_GOV,e7965e3a-1f49-4d67-a3de-ad1ce460bbcc,EXCHANGE_S_FOUNDATION_GOV,922ba911-5694-4e99-a794-73aed9bfeec8,Exchange Foundation for Government Dynamics 365 Field Service Contractor for Government,D365_FIELD_SERVICE_CONTRACTOR_GOV,e7965e3a-1f49-4d67-a3de-ad1ce460bbcc,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government @@ -253,27 +253,27 @@ Dynamics 365 for Case Management Enterprise Edition,DYN365_ENTERPRISE_CASE_MANAG Dynamics 365 for Case Management Enterprise Edition,DYN365_ENTERPRISE_CASE_MANAGEMENT,d39fb075-21ae-42d0-af80-22a2599749e0,SHAREPOINTENTERPRISE,5dbe027f-2339-4123-9542-606e4d348a72,SharePoint (Plan 2) Dynamics 365 for Case Management Enterprise Edition,DYN365_ENTERPRISE_CASE_MANAGEMENT,d39fb075-21ae-42d0-af80-22a2599749e0,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,Power Apps for Dynamics 365 Dynamics 365 for Case Management Enterprise Edition,DYN365_ENTERPRISE_CASE_MANAGEMENT,d39fb075-21ae-42d0-af80-22a2599749e0,FLOW_DYN_APPS,7e6d7d78-73de-46ba-83b1-6d25117334ba,Power Automate for Dynamics 365 -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,79bb0a8d-e686-4e16-ac59-2b3fd0014a61,Dynamics 365 for Case Management for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,EXCHANGE_S_FOUNDATION_GOV,922ba911-5694-4e99-a794-73aed9bfeec8,Exchange Foundation for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,79bb0a8d-e686-4e16-ac59-2b3fd0014a61,Dynamics 365 for Case Management for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,79bb0a8d-e686-4e16-ac59-2b3fd0014a61,Dynamics 365 for Case Management for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,EXCHANGE_S_FOUNDATION_GOV,922ba911-5694-4e99-a794-73aed9bfeec8,Exchange Foundation for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,79bb0a8d-e686-4e16-ac59-2b3fd0014a61,Dynamics 365 for Case Management for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_CDS_RETAIL,93cc200d-a47f-4c56-aec1-83f8b0d0425a,Common Data Service for Dynamics 365 Retail Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,FLOW_FOR_IOM_USL,9e6d1620-dce9-4655-8933-af8fa5bccc9c,Data Integration for IOM with Power Automate USL Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,CDS_FOR_IOM,2bb89402-51e9-4c5a-be33-e954a9dd1ba6,Dataverse for IOM Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_RETAIL,117e3aa0-8d08-4a19-a6a5-90b7a96e2128,Dynamics 365 Commerce -Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service +Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,"Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service" Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_FP_ACC_PROTECTION,4c00c16c-0304-4421-b598-555c3e78edcb,Dynamics 365 Fraud Protection - Account Protection Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_FP_LOSS_PREVENTION,ecc62904-fa88-4552-a62c-fe582fb31444,Dynamics 365 Fraud Protection - Loss Prevention Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_FP_PURCH_PROTECTION,d703990f-006e-459b-b8dd-1267c4533a22,Dynamics 365 Fraud Protection - Purchase Protection @@ -296,14 +296,14 @@ Dynamics 365 for Customer Service Enterprise Edition,DYN365_ENTERPRISE_CUSTOMER_ Dynamics 365 for Customer Service Enterprise Edition,DYN365_ENTERPRISE_CUSTOMER_SERVICE,749742bf-0d37-4158-a120-33567104deeb,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,POWERAPPS FOR DYNAMICS 365 Dynamics 365 for Customer Service Enterprise Edition,DYN365_ENTERPRISE_CUSTOMER_SERVICE,749742bf-0d37-4158-a120-33567104deeb,SHAREPOINTENTERPRISE,5dbe027f-2339-4123-9542-606e4d348a72,DYNAMICS 365 FOR CUSTOMER SERVICE Dynamics 365 for Customer Service Enterprise Edition,DYN365_ENTERPRISE_CUSTOMER_SERVICE,749742bf-0d37-4158-a120-33567104deeb,SHAREPOINTWAC,e95bec33-7c88-4a70-8e19-b10bd9d0c014,OFFICE ONLINE -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,dc6643d9-1e72-4dce-9f64-1d6eac1f1c5a,Dynamics 365 for Customer Service for Government -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,Forms_Pro_Service_GCC,bb681a9b-58f5-42ee-9926-674325be8aaa,Microsoft Dynamics 365 Customer Voice for Customer Service Enterprise for GCC -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,dc6643d9-1e72-4dce-9f64-1d6eac1f1c5a,Dynamics 365 for Customer Service for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,Forms_Pro_Service_GCC,bb681a9b-58f5-42ee-9926-674325be8aaa,Microsoft Dynamics 365 Customer Voice for Customer Service Enterprise for GCC +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government Dynamics 365 for Field Service Attach to Qualifying Dynamics 365 Base Offer,D365_FIELD_SERVICE_ATTACH,a36cdaa2-a806-4b6e-9ae0-28dbd993c20e,D365_FIELD_SERVICE_ATTACH,55c9148b-d5f0-4101-b5a0-b2727cfc0916,Dynamics 365 for Field Service Attach Dynamics 365 for Field Service Attach to Qualifying Dynamics 365 Base Offer,D365_FIELD_SERVICE_ATTACH,a36cdaa2-a806-4b6e-9ae0-28dbd993c20e,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 for Field Service Enterprise Edition,DYN365_ENTERPRISE_FIELD_SERVICE,c7d15985-e746-4f01-b113-20b575898250,DYN365_ENTERPRISE_FIELD_SERVICE,8c66ef8a-177f-4c0d-853c-d4f219331d09,Dynamics 365 for Field Service @@ -393,13 +393,13 @@ Dynamics 365 for Sales Enterprise Edition,DYN365_ENTERPRISE_SALES,1e1a282c-9c54- Dynamics 365 for Sales Enterprise Edition,DYN365_ENTERPRISE_SALES,1e1a282c-9c54-43a2-9310-98ef728faace,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,PROJECT ONLINE ESSENTIALS Dynamics 365 for Sales Enterprise Edition,DYN365_ENTERPRISE_SALES,1e1a282c-9c54-43a2-9310-98ef728faace,SHAREPOINTENTERPRISE,5dbe027f-2339-4123-9542-606e4d348a72,SHAREPOINT ONLINE (PLAN 2) Dynamics 365 for Sales Enterprise Edition,DYN365_ENTERPRISE_SALES,1e1a282c-9c54-43a2-9310-98ef728faace,SHAREPOINTWAC,e95bec33-7c88-4a70-8e19-b10bd9d0c014,OFFICE ONLINE -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,DYN365_ENTERPRISE_SALES_GOV,213be507-d547-4f79-bc2c-6196bc54c4a3,Dynamics 365 for Sales for Government -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,DYN365_ENTERPRISE_SALES_GOV,213be507-d547-4f79-bc2c-6196bc54c4a3,Dynamics 365 for Sales for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,DYN365_ENTERPRISE_SALES_GOV,213be507-d547-4f79-bc2c-6196bc54c4a3,Dynamics 365 for Sales for Government Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,Forms_Pro_SalesEnt_GCC,33850b82-0a37-4ebb-a0b2-ee163facd716,Microsoft Dynamics 365 Customer Voice for Sales Enterprise for GCC Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User @@ -411,12 +411,12 @@ Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3 Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,DYN365_ENTERPRISE_P1,d56f3deb-50d8-465a-bedb-f079817ccac1,Dynamics 365 Customer Engagement Plan -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,Forms_Pro_Service,67bf4812-f90b-4db9-97e7-c0bbbf7b2d09,Microsoft Dynamics 365 Customer Voice for Customer Service Enterprise -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,Power Apps for Dynamics 365 -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,FLOW_DYN_APPS,7e6d7d78-73de-46ba-83b1-6d25117334ba,Power Automate for Dynamics 365 -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,Project Online Essentials +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,DYN365_ENTERPRISE_P1,d56f3deb-50d8-465a-bedb-f079817ccac1,Dynamics 365 Customer Engagement Plan +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,Forms_Pro_Service,67bf4812-f90b-4db9-97e7-c0bbbf7b2d09,Microsoft Dynamics 365 Customer Voice for Customer Service Enterprise +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,Power Apps for Dynamics 365 +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,FLOW_DYN_APPS,7e6d7d78-73de-46ba-83b1-6d25117334ba,Power Automate for Dynamics 365 +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,Project Online Essentials Dynamics 365 Sales Premium,DYN365_SALES_PREMIUM,2edaa1dc-966d-4475-93d6-8ee8dfd96877,DYN365_SALES_INSIGHTS,fedc185f-0711-4cc0-80ed-0a92da1a8384,Dynamics 365 AI for Sales (Embedded) Dynamics 365 Sales Premium,DYN365_SALES_PREMIUM,2edaa1dc-966d-4475-93d6-8ee8dfd96877,SHAREPOINTENTERPRISE,5dbe027f-2339-4123-9542-606e4d348a72,SharePoint (Plan 2) Dynamics 365 Sales Premium,DYN365_SALES_PREMIUM,2edaa1dc-966d-4475-93d6-8ee8dfd96877,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,Project Online Essentials @@ -432,7 +432,7 @@ Dynamics 365 Sales Premium,DYN365_SALES_PREMIUM,2edaa1dc-966d-4475-93d6-8ee8dfd9 Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,DYN365_CDS_SUPPLYCHAINMANAGEMENT,b6a8b974-2956-4e14-ae81-f0384c363528,Common Data Service for Dynamics 365 Supply Chain Management Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,CDS_FOR_IOM,2bb89402-51e9-4c5a-be33-e954a9dd1ba6,Dataverse for IOM -Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service +Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,"Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service" Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,D365_SCM_Attach,b21c777f-c2d5-486e-88f6-fc0a3e474271,Dynamics 365 for Supply Chain Management Attach Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 for Marketing Business Edition,DYN365_BUSINESS_MARKETING,238e2f8d-e429-4035-94db-6926be4ffe7b,DYN365_BUSINESS_Marketing,393a0c96-9ba1-4af0-8975-fa2f853a25ac,Dynamics 365 Marketing @@ -521,7 +521,7 @@ Dynamics 365 P1 Tria for Information Workers,DYN365_ENTERPRISE_P1_IW,338148b6-1b Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,D365CDSforProjectOperations,7df1d500-ca5c-4229-8cea-815bc88798c9,Common Data Service for Dynamics 365 Project Operations Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,D365_ProjectOperationsCDS,18fa3aba-b085-4105-87d7-55617b8585e6,Dynamics 365 Project Operations CDS Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User -Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service +Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,"Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service" Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,D365_ProjectOperations,69f07c66-bee4-4222-b051-195095efee5b,Dynamics 365 Project Operations Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,Power Apps for Dynamics 365 Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,FLOW_DYN_APPS,7e6d7d78-73de-46ba-83b1-6d25117334ba,Power Automate for Dynamics 365 @@ -4797,18 +4797,18 @@ Power Pages authenticated users T2 min 100 units - 100 users/per site/month capa Power Pages authenticated users T2 min 100 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH,Power_Pages_authenticated_users_T2_min_100_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH,7cae5432-61bb-48c3-b75c-831394ec13a0,PowerPages_Authenticated_Users_GCCH,5410f688-68f2-47a5-9b8f-7466194a806a,Power Pages Authenticated Users per site mthly capacity GCCH New Power Pages authenticated users T2 min 100 units - 100 users/per site/month capacity pack CN_CN,Power Pages authenticated users T2_CN_CN,7d2bb54a-a870-41c2-98d1-1f3b5b523275,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site Power Pages authenticated users T2 min 100 units - 100 users/per site/month capacity pack CN_CN,Power Pages authenticated users T2_CN_CN,7d2bb54a-a870-41c2-98d1-1f3b5b523275,PowerPages_Authenticated_User_CN,967d9574-a076-4bb7-ab89-f41f64bc142e,Power Pages Authenticated Users per site monthly capacity China -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack CN_CN,Power Pages authenticated users T3_CN_CN,2cfd692f-a352-4fa8-b960-e3ad0c9b1178,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack CN_CN,Power Pages authenticated users T3_CN_CN,2cfd692f-a352-4fa8-b960-e3ad0c9b1178,PowerPages_Authenticated_User_CN,967d9574-a076-4bb7-ab89-f41f64bc142e,Power Pages Authenticated Users per site monthly capacity China -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack,878b8bbd-3cd0-4b44-9a56-3406741e65e0,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack,878b8bbd-3cd0-4b44-9a56-3406741e65e0,PowerPages_Authenticated_User,0d3366f3-266e-4117-b422-7cabbc165e7c,Power Pages Authenticated Users per site monthly capacity -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack,878b8bbd-3cd0-4b44-9a56-3406741e65e0,PowerPages_Authenticated_User_GCCH,18e74ca2-b5f0-4802-9a8b-00d2ff1e8322,Power Pages Authenticated Users per site monthly capacity GCCH -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_GCC,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_GCC,53265c61-c78c-4223-ab30-422da0c97fbb,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_GCC,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_GCC,53265c61-c78c-4223-ab30-422da0c97fbb,PowerPages_Authenticated_User_GCC,cdf787bd-1546-48d2-9e93-b21f9ea7067a,Power Pages Authenticated Users per site monthly capacity GCC -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_DOD,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_DOD,398d37b5-8deb-48db-8f7f-703eb2fb7c72,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_DOD,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_DOD,398d37b5-8deb-48db-8f7f-703eb2fb7c72,PowerPages_Authenticated_User_DoD,03300fea-7a88-45a6-b5bd-29653803c591,Power Pages Authenticated Users per site monthly capacity DoD -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH,01d46c34-3525-47d5-bd1a-5f19979938a0,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH,01d46c34-3525-47d5-bd1a-5f19979938a0,PowerPages_Authenticated_User_GCCH,18e74ca2-b5f0-4802-9a8b-00d2ff1e8322,Power Pages Authenticated Users per site monthly capacity GCCH -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH,01d46c34-3525-47d5-bd1a-5f19979938a0,PowerPages_Authenticated_Users_GCCH,5410f688-68f2-47a5-9b8f-7466194a806a,Power Pages Authenticated Users per site mthly capacity GCCH New +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack CN_CN",Power Pages authenticated users T3_CN_CN,2cfd692f-a352-4fa8-b960-e3ad0c9b1178,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack CN_CN",Power Pages authenticated users T3_CN_CN,2cfd692f-a352-4fa8-b960-e3ad0c9b1178,PowerPages_Authenticated_User_CN,967d9574-a076-4bb7-ab89-f41f64bc142e,Power Pages Authenticated Users per site monthly capacity China +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack",878b8bbd-3cd0-4b44-9a56-3406741e65e0,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack",878b8bbd-3cd0-4b44-9a56-3406741e65e0,PowerPages_Authenticated_User,0d3366f3-266e-4117-b422-7cabbc165e7c,Power Pages Authenticated Users per site monthly capacity +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack",878b8bbd-3cd0-4b44-9a56-3406741e65e0,PowerPages_Authenticated_User_GCCH,18e74ca2-b5f0-4802-9a8b-00d2ff1e8322,Power Pages Authenticated Users per site monthly capacity GCCH +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_GCC","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_GCC",53265c61-c78c-4223-ab30-422da0c97fbb,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_GCC","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_GCC",53265c61-c78c-4223-ab30-422da0c97fbb,PowerPages_Authenticated_User_GCC,cdf787bd-1546-48d2-9e93-b21f9ea7067a,Power Pages Authenticated Users per site monthly capacity GCC +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_DOD","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_DOD",398d37b5-8deb-48db-8f7f-703eb2fb7c72,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_DOD","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_DOD",398d37b5-8deb-48db-8f7f-703eb2fb7c72,PowerPages_Authenticated_User_DoD,03300fea-7a88-45a6-b5bd-29653803c591,Power Pages Authenticated Users per site monthly capacity DoD +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH",01d46c34-3525-47d5-bd1a-5f19979938a0,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH",01d46c34-3525-47d5-bd1a-5f19979938a0,PowerPages_Authenticated_User_GCCH,18e74ca2-b5f0-4802-9a8b-00d2ff1e8322,Power Pages Authenticated Users per site monthly capacity GCCH +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH",01d46c34-3525-47d5-bd1a-5f19979938a0,PowerPages_Authenticated_Users_GCCH,5410f688-68f2-47a5-9b8f-7466194a806a,Power Pages Authenticated Users per site mthly capacity GCCH New Power Pages vTrial for Makers,Power_Pages_vTrial_for_Makers,3f9f06f5-3c31-472c-985f-62d9c10ec167,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Power Pages vTrial for Makers,Power_Pages_vTrial_for_Makers,3f9f06f5-3c31-472c-985f-62d9c10ec167,DYN365_CDS_VIRAL,17ab22cd-a0b3-4536-910a-cb6eb12696c0,Common Data Service Power Pages vTrial for Makers,Power_Pages_vTrial_for_Makers,3f9f06f5-3c31-472c-985f-62d9c10ec167,POWER_PAGES_VTRIAL,6817d093-2d30-4249-8bd6-774f01efa78c,Power Pages vTrial for Makers @@ -5146,7 +5146,7 @@ Windows 365 Business 2 vCPU 4 GB 64 GB,CPC_B_2C_4RAM_64GB,42e6818f-8966-444b-b7a Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) -Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,CPC_SS_2,9d2eed2c-b0c0-4a89-940c-bc303444a41b,Windows 365 Business 2 vCPU, 8 GB, 128 GB +Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,CPC_SS_2,9d2eed2c-b0c0-4a89-940c-bc303444a41b,"Windows 365 Business 2 vCPU, 8 GB, 128 GB" Windows 365 Business 2 vCPU 8 GB 256 GB,CPC_B_2C_8RAM_256GB,750d9542-a2f8-41c7-8c81-311352173432,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Windows 365 Business 2 vCPU 8 GB 256 GB,CPC_B_2C_8RAM_256GB,750d9542-a2f8-41c7-8c81-311352173432,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Windows 365 Business 2 vCPU 8 GB 256 GB,CPC_B_2C_8RAM_256GB,750d9542-a2f8-41c7-8c81-311352173432,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) @@ -5177,14 +5177,14 @@ Windows 365 Business 8 vCPU 32 GB 512 GB,CPC_B_8C_32RAM_512GB,8ee402cd-e6a8-4b67 Windows 365 Business 8 vCPU 32 GB 512 GB,CPC_B_8C_32RAM_512GB,8ee402cd-e6a8-4b67-a411-54d1f37a2049,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Windows 365 Business 8 vCPU 32 GB 512 GB,CPC_B_8C_32RAM_512GB,8ee402cd-e6a8-4b67-a411-54d1f37a2049,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) Windows 365 Business 8 vCPU 32 GB 512 GB,CPC_B_8C_32RAM_512GB,8ee402cd-e6a8-4b67-a411-54d1f37a2049,CPC_B_8C_32RAM_512GB,4229a0b4-7f34-4835-b068-6dc8d10be57c,Windows 365 Business 8 vCPU 32 GB 512 GB -Windows 365 Business 16 vCPU, 64 GB, 512 GB,Windows_365_Business_16_vCPU,_64_GB,_512_GB,93d9955a-ec70-44d5-8faa-a194492390f7,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Windows 365 Business 16 vCPU, 64 GB, 512 GB,Windows_365_Business_16_vCPU,_64_GB,_512_GB,93d9955a-ec70-44d5-8faa-a194492390f7,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) -Windows 365 Business 16 vCPU, 64 GB, 512 GB,Windows_365_Business_16_vCPU,_64_GB,_512_GB,93d9955a-ec70-44d5-8faa-a194492390f7,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) -Windows 365 Business 16 vCPU, 64 GB, 512 GB,Windows_365_Business_16_vCPU,_64_GB,_512_GB,93d9955a-ec70-44d5-8faa-a194492390f7,CPC_B_16C_64GB_512GB,cbbedc49-52d5-4fd6-82ac-a5bc51634dc3,Windows 365 Business 16 vCPU, 64 GB, 512 GB -Windows 365 Business 16 vCPU, 64 GB, 1 TB,Windows_365_Business_16_vCPU,_64_GB,_1_TB,24be3cd7-82ca-41a5-94a7-4903373cdcae,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Windows 365 Business 16 vCPU, 64 GB, 1 TB,Windows_365_Business_16_vCPU,_64_GB,_1_TB,24be3cd7-82ca-41a5-94a7-4903373cdcae,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) -Windows 365 Business 16 vCPU, 64 GB, 1 TB,Windows_365_Business_16_vCPU,_64_GB,_1_TB,24be3cd7-82ca-41a5-94a7-4903373cdcae,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) -Windows 365 Business 16 vCPU, 64 GB, 1 TB,Windows_365_Business_16_vCPU,_64_GB,_1_TB,24be3cd7-82ca-41a5-94a7-4903373cdcae,CPC_B_16C_64GB_1TB,37c961db-2cfd-4e13-b81e-b0059ce10e34,Windows 365 Business 16 vCPU, 64 GB, 1 TB +"Windows 365 Business 16 vCPU, 64 GB, 512 GB","Windows_365_Business_16_vCPU,_64_GB,_512_GB",93d9955a-ec70-44d5-8faa-a194492390f7,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Windows 365 Business 16 vCPU, 64 GB, 512 GB","Windows_365_Business_16_vCPU,_64_GB,_512_GB",93d9955a-ec70-44d5-8faa-a194492390f7,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) +"Windows 365 Business 16 vCPU, 64 GB, 512 GB","Windows_365_Business_16_vCPU,_64_GB,_512_GB",93d9955a-ec70-44d5-8faa-a194492390f7,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) +"Windows 365 Business 16 vCPU, 64 GB, 512 GB","Windows_365_Business_16_vCPU,_64_GB,_512_GB",93d9955a-ec70-44d5-8faa-a194492390f7,CPC_B_16C_64GB_512GB,cbbedc49-52d5-4fd6-82ac-a5bc51634dc3,"Windows 365 Business 16 vCPU, 64 GB, 512 GB" +"Windows 365 Business 16 vCPU, 64 GB, 1 TB","Windows_365_Business_16_vCPU,_64_GB,_1_TB",24be3cd7-82ca-41a5-94a7-4903373cdcae,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Windows 365 Business 16 vCPU, 64 GB, 1 TB","Windows_365_Business_16_vCPU,_64_GB,_1_TB",24be3cd7-82ca-41a5-94a7-4903373cdcae,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) +"Windows 365 Business 16 vCPU, 64 GB, 1 TB","Windows_365_Business_16_vCPU,_64_GB,_1_TB",24be3cd7-82ca-41a5-94a7-4903373cdcae,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) +"Windows 365 Business 16 vCPU, 64 GB, 1 TB","Windows_365_Business_16_vCPU,_64_GB,_1_TB",24be3cd7-82ca-41a5-94a7-4903373cdcae,CPC_B_16C_64GB_1TB,37c961db-2cfd-4e13-b81e-b0059ce10e34,"Windows 365 Business 16 vCPU, 64 GB, 1 TB" Windows 365 Enterprise 1 vCPU 2 GB 64 GB,CPC_E_1C_2GB_64GB,0c278af4-c9c1-45de-9f4b-cd929e747a2c,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Windows 365 Enterprise 1 vCPU 2 GB 64 GB,CPC_E_1C_2GB_64GB,0c278af4-c9c1-45de-9f4b-cd929e747a2c,CPC_E_1C_2GB_64GB,86d70dbb-d4c6-4662-ba17-3014204cbb28,Windows 365 Enterprise 1 vCPU 2 GB 64 GB Windows 365 Enterprise 2 vCPU 4 GB 64 GB,CPC_E_2C_4GB_64GB,7bb14422-3b90-4389-a7be-f1b745fc037f,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation diff --git a/Modules/CippExtensions/Public/ConversionTable.csv b/Modules/CippExtensions/Public/ConversionTable.csv index 4463224224a6..e38e1d159430 100644 --- a/Modules/CippExtensions/Public/ConversionTable.csv +++ b/Modules/CippExtensions/Public/ConversionTable.csv @@ -228,9 +228,9 @@ Dynamics 365 - Additional Non-Production Instance for Government,CRMTESTINSTANCE Dynamics 365 - Additional Non-Production Instance for Government,CRMTESTINSTANCE_NOPREREQ,2cf302fe-62db-4e20-b573-e0998b1208b5,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 Enterprise Edition - Additional Production Instance for Government,CRMINSTANCE_GCC,2bd3cb20-1bb6-446b-b4d0-089af3a05c52,CRMINSTANCE_GCC,483cc331-f4df-4a3b-b8ca-fe1a247569f6,Microsoft Dynamics CRM Online Instance Dynamics 365 Enterprise Edition - Additional Production Instance for Government,CRMINSTANCE_GCC,2bd3cb20-1bb6-446b-b4d0-089af3a05c52,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization,CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,CRM_AUTO_ROUTING_ENGINE_ADDON,24435e4b-87d0-4d7d-8beb-63a9b1573022,Field Service – Automated Routing Engine Add-On -Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization,CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,CRM_AUTO_ROUTING_ADDON,2ba394e0-6f18-4b77-b45f-a5663bbab540,RETIRED - Field Service – Automated Routing Engine Add-On -Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization,CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization",CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,CRM_AUTO_ROUTING_ENGINE_ADDON,24435e4b-87d0-4d7d-8beb-63a9b1573022,Field Service – Automated Routing Engine Add-On +"Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization",CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,CRM_AUTO_ROUTING_ADDON,2ba394e0-6f18-4b77-b45f-a5663bbab540,RETIRED - Field Service – Automated Routing Engine Add-On +"Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization",CRM_AUTO_ROUTING_ADDON,977464c4-bfaf-4b67-b761-a9bb735a2196,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 Field Service Contractor for Government,D365_FIELD_SERVICE_CONTRACTOR_GOV,e7965e3a-1f49-4d67-a3de-ad1ce460bbcc,CDS_FIELD_SERVICE_CONTRACTOR_GCC,2457fe40-65be-48a1-935f-924ad6e62dba,Common Data Service Field service Part Time Contractors for Government Dynamics 365 Field Service Contractor for Government,D365_FIELD_SERVICE_CONTRACTOR_GOV,e7965e3a-1f49-4d67-a3de-ad1ce460bbcc,EXCHANGE_S_FOUNDATION_GOV,922ba911-5694-4e99-a794-73aed9bfeec8,Exchange Foundation for Government Dynamics 365 Field Service Contractor for Government,D365_FIELD_SERVICE_CONTRACTOR_GOV,e7965e3a-1f49-4d67-a3de-ad1ce460bbcc,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government @@ -253,27 +253,27 @@ Dynamics 365 for Case Management Enterprise Edition,DYN365_ENTERPRISE_CASE_MANAG Dynamics 365 for Case Management Enterprise Edition,DYN365_ENTERPRISE_CASE_MANAGEMENT,d39fb075-21ae-42d0-af80-22a2599749e0,SHAREPOINTENTERPRISE,5dbe027f-2339-4123-9542-606e4d348a72,SharePoint (Plan 2) Dynamics 365 for Case Management Enterprise Edition,DYN365_ENTERPRISE_CASE_MANAGEMENT,d39fb075-21ae-42d0-af80-22a2599749e0,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,Power Apps for Dynamics 365 Dynamics 365 for Case Management Enterprise Edition,DYN365_ENTERPRISE_CASE_MANAGEMENT,d39fb075-21ae-42d0-af80-22a2599749e0,FLOW_DYN_APPS,7e6d7d78-73de-46ba-83b1-6d25117334ba,Power Automate for Dynamics 365 -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,79bb0a8d-e686-4e16-ac59-2b3fd0014a61,Dynamics 365 for Case Management for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,EXCHANGE_S_FOUNDATION_GOV,922ba911-5694-4e99-a794-73aed9bfeec8,Exchange Foundation for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,79bb0a8d-e686-4e16-ac59-2b3fd0014a61,Dynamics 365 for Case Management for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government -Dynamics 365 for Case Management, Enterprise Edition for Government,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,79bb0a8d-e686-4e16-ac59-2b3fd0014a61,Dynamics 365 for Case Management for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,EXCHANGE_S_FOUNDATION_GOV,922ba911-5694-4e99-a794-73aed9bfeec8,Exchange Foundation for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",D365_ENTERPRISE_CASE_MANAGEMENT_GOV,5cd0b796-9ac8-4792-9f0b-796ca9044e4a,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,79bb0a8d-e686-4e16-ac59-2b3fd0014a61,Dynamics 365 for Case Management for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government +"Dynamics 365 for Case Management, Enterprise Edition for Government",DYN365_ENTERPRISE_CASE_MANAGEMENT_GOV,ff5a82be-1edd-4d48-94e0-52527825b589,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_CDS_RETAIL,93cc200d-a47f-4c56-aec1-83f8b0d0425a,Common Data Service for Dynamics 365 Retail Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,FLOW_FOR_IOM_USL,9e6d1620-dce9-4655-8933-af8fa5bccc9c,Data Integration for IOM with Power Automate USL Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,CDS_FOR_IOM,2bb89402-51e9-4c5a-be33-e954a9dd1ba6,Dataverse for IOM Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_RETAIL,117e3aa0-8d08-4a19-a6a5-90b7a96e2128,Dynamics 365 Commerce -Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service +Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,"Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service" Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_FP_ACC_PROTECTION,4c00c16c-0304-4421-b598-555c3e78edcb,Dynamics 365 Fraud Protection - Account Protection Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_FP_LOSS_PREVENTION,ecc62904-fa88-4552-a62c-fe582fb31444,Dynamics 365 Fraud Protection - Loss Prevention Dynamics 365 Commerce,DYN365_RETAIL,79909bd8-4c69-4202-939e-11bc4385b134,DYN365_FP_PURCH_PROTECTION,d703990f-006e-459b-b8dd-1267c4533a22,Dynamics 365 Fraud Protection - Purchase Protection @@ -296,14 +296,14 @@ Dynamics 365 for Customer Service Enterprise Edition,DYN365_ENTERPRISE_CUSTOMER_ Dynamics 365 for Customer Service Enterprise Edition,DYN365_ENTERPRISE_CUSTOMER_SERVICE,749742bf-0d37-4158-a120-33567104deeb,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,POWERAPPS FOR DYNAMICS 365 Dynamics 365 for Customer Service Enterprise Edition,DYN365_ENTERPRISE_CUSTOMER_SERVICE,749742bf-0d37-4158-a120-33567104deeb,SHAREPOINTENTERPRISE,5dbe027f-2339-4123-9542-606e4d348a72,DYNAMICS 365 FOR CUSTOMER SERVICE Dynamics 365 for Customer Service Enterprise Edition,DYN365_ENTERPRISE_CUSTOMER_SERVICE,749742bf-0d37-4158-a120-33567104deeb,SHAREPOINTWAC,e95bec33-7c88-4a70-8e19-b10bd9d0c014,OFFICE ONLINE -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,dc6643d9-1e72-4dce-9f64-1d6eac1f1c5a,Dynamics 365 for Customer Service for Government -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,Forms_Pro_Service_GCC,bb681a9b-58f5-42ee-9926-674325be8aaa,Microsoft Dynamics 365 Customer Voice for Customer Service Enterprise for GCC -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government -Dynamics 365 for Customer Service, Enterprise Edition for Government,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,dc6643d9-1e72-4dce-9f64-1d6eac1f1c5a,Dynamics 365 for Customer Service for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,Forms_Pro_Service_GCC,bb681a9b-58f5-42ee-9926-674325be8aaa,Microsoft Dynamics 365 Customer Voice for Customer Service Enterprise for GCC +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government +"Dynamics 365 for Customer Service, Enterprise Edition for Government",DYN365_ENTERPRISE_CUSTOMER_SERVICE_GOV,3c74d823-8f01-4fe8-82d5-f089a5504cec,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government Dynamics 365 for Field Service Attach to Qualifying Dynamics 365 Base Offer,D365_FIELD_SERVICE_ATTACH,a36cdaa2-a806-4b6e-9ae0-28dbd993c20e,D365_FIELD_SERVICE_ATTACH,55c9148b-d5f0-4101-b5a0-b2727cfc0916,Dynamics 365 for Field Service Attach Dynamics 365 for Field Service Attach to Qualifying Dynamics 365 Base Offer,D365_FIELD_SERVICE_ATTACH,a36cdaa2-a806-4b6e-9ae0-28dbd993c20e,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 for Field Service Enterprise Edition,DYN365_ENTERPRISE_FIELD_SERVICE,c7d15985-e746-4f01-b113-20b575898250,DYN365_ENTERPRISE_FIELD_SERVICE,8c66ef8a-177f-4c0d-853c-d4f219331d09,Dynamics 365 for Field Service @@ -393,13 +393,13 @@ Dynamics 365 for Sales Enterprise Edition,DYN365_ENTERPRISE_SALES,1e1a282c-9c54- Dynamics 365 for Sales Enterprise Edition,DYN365_ENTERPRISE_SALES,1e1a282c-9c54-43a2-9310-98ef728faace,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,PROJECT ONLINE ESSENTIALS Dynamics 365 for Sales Enterprise Edition,DYN365_ENTERPRISE_SALES,1e1a282c-9c54-43a2-9310-98ef728faace,SHAREPOINTENTERPRISE,5dbe027f-2339-4123-9542-606e4d348a72,SHAREPOINT ONLINE (PLAN 2) Dynamics 365 for Sales Enterprise Edition,DYN365_ENTERPRISE_SALES,1e1a282c-9c54-43a2-9310-98ef728faace,SHAREPOINTWAC,e95bec33-7c88-4a70-8e19-b10bd9d0c014,OFFICE ONLINE -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,DYN365_ENTERPRISE_SALES_GOV,213be507-d547-4f79-bc2c-6196bc54c4a3,Dynamics 365 for Sales for Government -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government -Dynamics 365 for Sales, Enterprise Edition for Government,DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,DYN365_ENTERPRISE_SALES_GOV,213be507-d547-4f79-bc2c-6196bc54c4a3,Dynamics 365 for Sales for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,SHAREPOINTWAC_GOV,8f9f0f3b-ca90-406c-a842-95579171f8ec,Office for the Web for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,PROJECT_ESSENTIALS_GOV,fdcb7064-f45c-46fa-b056-7e0e9fdf4bf3,Project Online Essentials for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government +"Dynamics 365 for Sales, Enterprise Edition for Government",DYN365_ENTERPRISE_SALES_GOV,28b275ce-aec7-4c26-82e2-1ffbc2746ad4,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,DYN365_ENTERPRISE_SALES_GOV,213be507-d547-4f79-bc2c-6196bc54c4a3,Dynamics 365 for Sales for Government Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,Forms_Pro_SalesEnt_GCC,33850b82-0a37-4ebb-a0b2-ee163facd716,Microsoft Dynamics 365 Customer Voice for Sales Enterprise for GCC Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User @@ -411,12 +411,12 @@ Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3 Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,SHAREPOINTENTERPRISE_GOV,153f85dd-d912-4762-af6c-d6e0fb4f6692,SharePoint Plan 2G Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,FLOW_DYN_APPS_GOV,2c6af4f1-e7b6-4d59-bbc8-eaa884f42d69,Power Automate for Dynamics 365 for Government Dynamics 365 for Sales Enterprise for Government,D365_ENTERPRISE_SALES_GOV,e85b3345-2fd5-45cf-a196-7968d3e18e56,POWERAPPS_DYN_APPS_GOV,3089c02b-e533-4b73-96a5-01fa648c3c3c,PowerApps for Dynamics 365 for Government -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,DYN365_ENTERPRISE_P1,d56f3deb-50d8-465a-bedb-f079817ccac1,Dynamics 365 Customer Engagement Plan -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,Forms_Pro_Service,67bf4812-f90b-4db9-97e7-c0bbbf7b2d09,Microsoft Dynamics 365 Customer Voice for Customer Service Enterprise -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,Power Apps for Dynamics 365 -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,FLOW_DYN_APPS,7e6d7d78-73de-46ba-83b1-6d25117334ba,Power Automate for Dynamics 365 -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox,Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,Project Online Essentials +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,DYN365_ENTERPRISE_P1,d56f3deb-50d8-465a-bedb-f079817ccac1,Dynamics 365 Customer Engagement Plan +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,Forms_Pro_Service,67bf4812-f90b-4db9-97e7-c0bbbf7b2d09,Microsoft Dynamics 365 Customer Voice for Customer Service Enterprise +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,Power Apps for Dynamics 365 +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,FLOW_DYN_APPS,7e6d7d78-73de-46ba-83b1-6d25117334ba,Power Automate for Dynamics 365 +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox",Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox,494721b8-1f30-4315-aba6-70ca169358d9,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,Project Online Essentials Dynamics 365 Sales Premium,DYN365_SALES_PREMIUM,2edaa1dc-966d-4475-93d6-8ee8dfd96877,DYN365_SALES_INSIGHTS,fedc185f-0711-4cc0-80ed-0a92da1a8384,Dynamics 365 AI for Sales (Embedded) Dynamics 365 Sales Premium,DYN365_SALES_PREMIUM,2edaa1dc-966d-4475-93d6-8ee8dfd96877,SHAREPOINTENTERPRISE,5dbe027f-2339-4123-9542-606e4d348a72,SharePoint (Plan 2) Dynamics 365 Sales Premium,DYN365_SALES_PREMIUM,2edaa1dc-966d-4475-93d6-8ee8dfd96877,PROJECT_ESSENTIALS,1259157c-8581-4875-bca7-2ffb18c51bda,Project Online Essentials @@ -432,7 +432,7 @@ Dynamics 365 Sales Premium,DYN365_SALES_PREMIUM,2edaa1dc-966d-4475-93d6-8ee8dfd9 Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,DYN365_CDS_SUPPLYCHAINMANAGEMENT,b6a8b974-2956-4e14-ae81-f0384c363528,Common Data Service for Dynamics 365 Supply Chain Management Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,CDS_FOR_IOM,2bb89402-51e9-4c5a-be33-e954a9dd1ba6,Dataverse for IOM -Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service +Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,"Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service" Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,D365_SCM_Attach,b21c777f-c2d5-486e-88f6-fc0a3e474271,Dynamics 365 for Supply Chain Management Attach Dynamics 365 for Supply Chain Management Attach to Qualifying Dynamics 365 Base Offer,DYN365_SCM_ATTACH,090b4a96-8114-4c95-9c91-60e81ef53302,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 for Marketing Business Edition,DYN365_BUSINESS_MARKETING,238e2f8d-e429-4035-94db-6926be4ffe7b,DYN365_BUSINESS_Marketing,393a0c96-9ba1-4af0-8975-fa2f853a25ac,Dynamics 365 Marketing @@ -521,7 +521,7 @@ Dynamics 365 P1 Tria for Information Workers,DYN365_ENTERPRISE_P1_IW,338148b6-1b Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,D365CDSforProjectOperations,7df1d500-ca5c-4229-8cea-815bc88798c9,Common Data Service for Dynamics 365 Project Operations Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,D365_ProjectOperationsCDS,18fa3aba-b085-4105-87d7-55617b8585e6,Dynamics 365 Project Operations CDS Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User -Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service +Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,DYN365_REGULATORY_SERVICE,c7657ae3-c0b0-4eed-8c1d-6a7967bd9c65,"Dynamics 365 for Finance and Operations, Enterprise edition - Regulatory Service" Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,D365_ProjectOperations,69f07c66-bee4-4222-b051-195095efee5b,Dynamics 365 Project Operations Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,Power Apps for Dynamics 365 Dynamics 365 Project Operations,DYN365_PROJECT_OPERATIONS,98619618-9dc8-48c6-8f0c-741890ba5f93,FLOW_DYN_APPS,7e6d7d78-73de-46ba-83b1-6d25117334ba,Power Automate for Dynamics 365 @@ -4797,18 +4797,18 @@ Power Pages authenticated users T2 min 100 units - 100 users/per site/month capa Power Pages authenticated users T2 min 100 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH,Power_Pages_authenticated_users_T2_min_100_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH,7cae5432-61bb-48c3-b75c-831394ec13a0,PowerPages_Authenticated_Users_GCCH,5410f688-68f2-47a5-9b8f-7466194a806a,Power Pages Authenticated Users per site mthly capacity GCCH New Power Pages authenticated users T2 min 100 units - 100 users/per site/month capacity pack CN_CN,Power Pages authenticated users T2_CN_CN,7d2bb54a-a870-41c2-98d1-1f3b5b523275,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site Power Pages authenticated users T2 min 100 units - 100 users/per site/month capacity pack CN_CN,Power Pages authenticated users T2_CN_CN,7d2bb54a-a870-41c2-98d1-1f3b5b523275,PowerPages_Authenticated_User_CN,967d9574-a076-4bb7-ab89-f41f64bc142e,Power Pages Authenticated Users per site monthly capacity China -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack CN_CN,Power Pages authenticated users T3_CN_CN,2cfd692f-a352-4fa8-b960-e3ad0c9b1178,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack CN_CN,Power Pages authenticated users T3_CN_CN,2cfd692f-a352-4fa8-b960-e3ad0c9b1178,PowerPages_Authenticated_User_CN,967d9574-a076-4bb7-ab89-f41f64bc142e,Power Pages Authenticated Users per site monthly capacity China -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack,878b8bbd-3cd0-4b44-9a56-3406741e65e0,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack,878b8bbd-3cd0-4b44-9a56-3406741e65e0,PowerPages_Authenticated_User,0d3366f3-266e-4117-b422-7cabbc165e7c,Power Pages Authenticated Users per site monthly capacity -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack,878b8bbd-3cd0-4b44-9a56-3406741e65e0,PowerPages_Authenticated_User_GCCH,18e74ca2-b5f0-4802-9a8b-00d2ff1e8322,Power Pages Authenticated Users per site monthly capacity GCCH -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_GCC,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_GCC,53265c61-c78c-4223-ab30-422da0c97fbb,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_GCC,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_GCC,53265c61-c78c-4223-ab30-422da0c97fbb,PowerPages_Authenticated_User_GCC,cdf787bd-1546-48d2-9e93-b21f9ea7067a,Power Pages Authenticated Users per site monthly capacity GCC -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_DOD,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_DOD,398d37b5-8deb-48db-8f7f-703eb2fb7c72,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_DOD,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_DOD,398d37b5-8deb-48db-8f7f-703eb2fb7c72,PowerPages_Authenticated_User_DoD,03300fea-7a88-45a6-b5bd-29653803c591,Power Pages Authenticated Users per site monthly capacity DoD -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH,01d46c34-3525-47d5-bd1a-5f19979938a0,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH,01d46c34-3525-47d5-bd1a-5f19979938a0,PowerPages_Authenticated_User_GCCH,18e74ca2-b5f0-4802-9a8b-00d2ff1e8322,Power Pages Authenticated Users per site monthly capacity GCCH -Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH,Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH,01d46c34-3525-47d5-bd1a-5f19979938a0,PowerPages_Authenticated_Users_GCCH,5410f688-68f2-47a5-9b8f-7466194a806a,Power Pages Authenticated Users per site mthly capacity GCCH New +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack CN_CN",Power Pages authenticated users T3_CN_CN,2cfd692f-a352-4fa8-b960-e3ad0c9b1178,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack CN_CN",Power Pages authenticated users T3_CN_CN,2cfd692f-a352-4fa8-b960-e3ad0c9b1178,PowerPages_Authenticated_User_CN,967d9574-a076-4bb7-ab89-f41f64bc142e,Power Pages Authenticated Users per site monthly capacity China +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack",878b8bbd-3cd0-4b44-9a56-3406741e65e0,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack",878b8bbd-3cd0-4b44-9a56-3406741e65e0,PowerPages_Authenticated_User,0d3366f3-266e-4117-b422-7cabbc165e7c,Power Pages Authenticated Users per site monthly capacity +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack",878b8bbd-3cd0-4b44-9a56-3406741e65e0,PowerPages_Authenticated_User_GCCH,18e74ca2-b5f0-4802-9a8b-00d2ff1e8322,Power Pages Authenticated Users per site monthly capacity GCCH +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_GCC","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_GCC",53265c61-c78c-4223-ab30-422da0c97fbb,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_GCC","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_GCC",53265c61-c78c-4223-ab30-422da0c97fbb,PowerPages_Authenticated_User_GCC,cdf787bd-1546-48d2-9e93-b21f9ea7067a,Power Pages Authenticated Users per site monthly capacity GCC +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_DOD","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_DOD",398d37b5-8deb-48db-8f7f-703eb2fb7c72,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_DOD","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_DOD",398d37b5-8deb-48db-8f7f-703eb2fb7c72,PowerPages_Authenticated_User_DoD,03300fea-7a88-45a6-b5bd-29653803c591,Power Pages Authenticated Users per site monthly capacity DoD +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH",01d46c34-3525-47d5-bd1a-5f19979938a0,DV_PowerPages_Authenticated_User,7aae746a-3463-4737-b295-3c1a16c31438,Dataverse for Power Pages Authenticated users per site +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH",01d46c34-3525-47d5-bd1a-5f19979938a0,PowerPages_Authenticated_User_GCCH,18e74ca2-b5f0-4802-9a8b-00d2ff1e8322,Power Pages Authenticated Users per site monthly capacity GCCH +"Power Pages authenticated users T3 min 1,000 units - 100 users/per site/month capacity pack_USGOV_GCCHIGH","Power_Pages_authenticated_users_T3_min_1,000_units_100_users/per_site/month_capacity_pack_USGOV_GCCHIGH",01d46c34-3525-47d5-bd1a-5f19979938a0,PowerPages_Authenticated_Users_GCCH,5410f688-68f2-47a5-9b8f-7466194a806a,Power Pages Authenticated Users per site mthly capacity GCCH New Power Pages vTrial for Makers,Power_Pages_vTrial_for_Makers,3f9f06f5-3c31-472c-985f-62d9c10ec167,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Power Pages vTrial for Makers,Power_Pages_vTrial_for_Makers,3f9f06f5-3c31-472c-985f-62d9c10ec167,DYN365_CDS_VIRAL,17ab22cd-a0b3-4536-910a-cb6eb12696c0,Common Data Service Power Pages vTrial for Makers,Power_Pages_vTrial_for_Makers,3f9f06f5-3c31-472c-985f-62d9c10ec167,POWER_PAGES_VTRIAL,6817d093-2d30-4249-8bd6-774f01efa78c,Power Pages vTrial for Makers @@ -5146,7 +5146,7 @@ Windows 365 Business 2 vCPU 4 GB 64 GB,CPC_B_2C_4RAM_64GB,42e6818f-8966-444b-b7a Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) -Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,CPC_SS_2,9d2eed2c-b0c0-4a89-940c-bc303444a41b,Windows 365 Business 2 vCPU, 8 GB, 128 GB +Windows 365 Business 2 vCPU 8 GB 128 GB,CPC_B_2C_8RAM_128GB,71f21848-f89b-4aaa-a2dc-780c8e8aac5b,CPC_SS_2,9d2eed2c-b0c0-4a89-940c-bc303444a41b,"Windows 365 Business 2 vCPU, 8 GB, 128 GB" Windows 365 Business 2 vCPU 8 GB 256 GB,CPC_B_2C_8RAM_256GB,750d9542-a2f8-41c7-8c81-311352173432,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Windows 365 Business 2 vCPU 8 GB 256 GB,CPC_B_2C_8RAM_256GB,750d9542-a2f8-41c7-8c81-311352173432,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Windows 365 Business 2 vCPU 8 GB 256 GB,CPC_B_2C_8RAM_256GB,750d9542-a2f8-41c7-8c81-311352173432,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) @@ -5177,14 +5177,14 @@ Windows 365 Business 8 vCPU 32 GB 512 GB,CPC_B_8C_32RAM_512GB,8ee402cd-e6a8-4b67 Windows 365 Business 8 vCPU 32 GB 512 GB,CPC_B_8C_32RAM_512GB,8ee402cd-e6a8-4b67-a411-54d1f37a2049,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Windows 365 Business 8 vCPU 32 GB 512 GB,CPC_B_8C_32RAM_512GB,8ee402cd-e6a8-4b67-a411-54d1f37a2049,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) Windows 365 Business 8 vCPU 32 GB 512 GB,CPC_B_8C_32RAM_512GB,8ee402cd-e6a8-4b67-a411-54d1f37a2049,CPC_B_8C_32RAM_512GB,4229a0b4-7f34-4835-b068-6dc8d10be57c,Windows 365 Business 8 vCPU 32 GB 512 GB -Windows 365 Business 16 vCPU, 64 GB, 512 GB,Windows_365_Business_16_vCPU,_64_GB,_512_GB,93d9955a-ec70-44d5-8faa-a194492390f7,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Windows 365 Business 16 vCPU, 64 GB, 512 GB,Windows_365_Business_16_vCPU,_64_GB,_512_GB,93d9955a-ec70-44d5-8faa-a194492390f7,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) -Windows 365 Business 16 vCPU, 64 GB, 512 GB,Windows_365_Business_16_vCPU,_64_GB,_512_GB,93d9955a-ec70-44d5-8faa-a194492390f7,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) -Windows 365 Business 16 vCPU, 64 GB, 512 GB,Windows_365_Business_16_vCPU,_64_GB,_512_GB,93d9955a-ec70-44d5-8faa-a194492390f7,CPC_B_16C_64GB_512GB,cbbedc49-52d5-4fd6-82ac-a5bc51634dc3,Windows 365 Business 16 vCPU, 64 GB, 512 GB -Windows 365 Business 16 vCPU, 64 GB, 1 TB,Windows_365_Business_16_vCPU,_64_GB,_1_TB,24be3cd7-82ca-41a5-94a7-4903373cdcae,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation -Windows 365 Business 16 vCPU, 64 GB, 1 TB,Windows_365_Business_16_vCPU,_64_GB,_1_TB,24be3cd7-82ca-41a5-94a7-4903373cdcae,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) -Windows 365 Business 16 vCPU, 64 GB, 1 TB,Windows_365_Business_16_vCPU,_64_GB,_1_TB,24be3cd7-82ca-41a5-94a7-4903373cdcae,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) -Windows 365 Business 16 vCPU, 64 GB, 1 TB,Windows_365_Business_16_vCPU,_64_GB,_1_TB,24be3cd7-82ca-41a5-94a7-4903373cdcae,CPC_B_16C_64GB_1TB,37c961db-2cfd-4e13-b81e-b0059ce10e34,Windows 365 Business 16 vCPU, 64 GB, 1 TB +"Windows 365 Business 16 vCPU, 64 GB, 512 GB","Windows_365_Business_16_vCPU,_64_GB,_512_GB",93d9955a-ec70-44d5-8faa-a194492390f7,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Windows 365 Business 16 vCPU, 64 GB, 512 GB","Windows_365_Business_16_vCPU,_64_GB,_512_GB",93d9955a-ec70-44d5-8faa-a194492390f7,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) +"Windows 365 Business 16 vCPU, 64 GB, 512 GB","Windows_365_Business_16_vCPU,_64_GB,_512_GB",93d9955a-ec70-44d5-8faa-a194492390f7,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) +"Windows 365 Business 16 vCPU, 64 GB, 512 GB","Windows_365_Business_16_vCPU,_64_GB,_512_GB",93d9955a-ec70-44d5-8faa-a194492390f7,CPC_B_16C_64GB_512GB,cbbedc49-52d5-4fd6-82ac-a5bc51634dc3,"Windows 365 Business 16 vCPU, 64 GB, 512 GB" +"Windows 365 Business 16 vCPU, 64 GB, 1 TB","Windows_365_Business_16_vCPU,_64_GB,_1_TB",24be3cd7-82ca-41a5-94a7-4903373cdcae,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +"Windows 365 Business 16 vCPU, 64 GB, 1 TB","Windows_365_Business_16_vCPU,_64_GB,_1_TB",24be3cd7-82ca-41a5-94a7-4903373cdcae,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) +"Windows 365 Business 16 vCPU, 64 GB, 1 TB","Windows_365_Business_16_vCPU,_64_GB,_1_TB",24be3cd7-82ca-41a5-94a7-4903373cdcae,M365_LIGHTHOUSE_PARTNER_PLAN1,d55411c9-cfff-40a9-87c7-240f14df7da5,Microsoft 365 Lighthouse (Plan 2) +"Windows 365 Business 16 vCPU, 64 GB, 1 TB","Windows_365_Business_16_vCPU,_64_GB,_1_TB",24be3cd7-82ca-41a5-94a7-4903373cdcae,CPC_B_16C_64GB_1TB,37c961db-2cfd-4e13-b81e-b0059ce10e34,"Windows 365 Business 16 vCPU, 64 GB, 1 TB" Windows 365 Enterprise 1 vCPU 2 GB 64 GB,CPC_E_1C_2GB_64GB,0c278af4-c9c1-45de-9f4b-cd929e747a2c,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Windows 365 Enterprise 1 vCPU 2 GB 64 GB,CPC_E_1C_2GB_64GB,0c278af4-c9c1-45de-9f4b-cd929e747a2c,CPC_E_1C_2GB_64GB,86d70dbb-d4c6-4662-ba17-3014204cbb28,Windows 365 Enterprise 1 vCPU 2 GB 64 GB Windows 365 Enterprise 2 vCPU 4 GB 64 GB,CPC_E_2C_4GB_64GB,7bb14422-3b90-4389-a7be-f1b745fc037f,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation diff --git a/Tools/Update-LicenseSKUFiles.ps1 b/Tools/Update-LicenseSKUFiles.ps1 index 5d8e49a766d9..e3f41a4df698 100644 --- a/Tools/Update-LicenseSKUFiles.ps1 +++ b/Tools/Update-LicenseSKUFiles.ps1 @@ -27,14 +27,16 @@ $licenseCsvURL = 'https://download.microsoft.com/download/e/3/e/e3e9faf2-f28b-49 $TempLicenseDataFile = "$ENV:TEMP\LicenseSKUs.csv" Invoke-WebRequest -Uri $licenseCsvURL -OutFile $TempLicenseDataFile $LicenseDataFile = Get-Item -Path $TempLicenseDataFile -$LicenseData = Import-Csv -Path $LicenseDataFile.FullName -Encoding utf8BOM +$LicenseData = Import-Csv -Path $LicenseDataFile.FullName -Encoding utf8BOM -Delimiter ',' # Update ConversionTable.csv with the latest license SKU data Set-Location $PSScriptRoot Set-Location .. $ConversionTableFiles = Get-ChildItem -Path *ConversionTable.csv -Recurse -File +Write-Host "Updating $($ConversionTableFiles.Count) ConversionTable.csv files with the latest license SKU data..." -ForegroundColor Yellow foreach ($File in $ConversionTableFiles) { - $LicenseData | Export-Csv -Path $File.FullName -NoTypeInformation -Force -Encoding utf8 -UseQuotes Never + $LicenseData | Export-Csv -Path $File.FullName -NoTypeInformation -Force -Encoding utf8 -UseQuotes AsNeeded + Write-Host "Updated $($File.FullName) with new license SKU data." -ForegroundColor Green } @@ -45,8 +47,11 @@ Set-Location .. Set-Location CIPP\src\data $LicenseJSONFiles = Get-ChildItem -Path *M365Licenses.json -File +Write-Host "Updating $($LicenseJSONFiles.Count) M365 license JSON files with the latest license SKU data..." -ForegroundColor Yellow + foreach ($File in $LicenseJSONFiles) { ConvertTo-Json -InputObject $LicenseData -Depth 100 | Set-Content -Path $File.FullName -Encoding utf8 + Write-Host "Updated $($File.FullName) with new license SKU data." -ForegroundColor Green } # Clean up the temporary license SKU CSV file From 1d9167c38c70497e4da04a9a769157f535b5ff35 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Thu, 27 Feb 2025 18:40:47 -0500 Subject: [PATCH 088/167] feat: add feature update policy also fix issue with spaces between commas for group assignment for esco --- .../Entrypoints/Invoke-ListIntunePolicy.ps1 | 86 ++++++++++--------- .../Public/New-CIPPIntuneTemplate.ps1 | 6 ++ .../Public/Set-CIPPAssignedPolicy.ps1 | 24 +++--- .../CIPPCore/Public/Set-CIPPIntunePolicy.ps1 | 19 ++++ 4 files changed, 83 insertions(+), 52 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntunePolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntunePolicy.ps1 index d8febbcf029b..a54285faeef4 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntunePolicy.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntunePolicy.ps1 @@ -38,6 +38,11 @@ Function Invoke-ListIntunePolicy { method = 'GET' url = "/deviceManagement/windowsDriverUpdateProfiles?`$expand=assignments&top=200" } + @{ + id = 'WindowsFeatureUpdateProfiles' + method = 'GET' + url = "/deviceManagement/windowsFeatureUpdateProfiles?`$expand=assignments&top=200" + } @{ id = 'GroupPolicyConfigurations' method = 'GET' @@ -58,48 +63,49 @@ Function Invoke-ListIntunePolicy { $BulkResults = New-GraphBulkRequest -Requests $BulkRequests -tenantid $TenantFilter $GraphRequest = $BulkResults | ForEach-Object { - $URLName = $_.Id - $_.body.Value | ForEach-Object { - $policyTypeName = switch -Wildcard ($_.'assignments@odata.context') { - '*microsoft.graph.windowsIdentityProtectionConfiguration*' { 'Identity Protection' } - '*microsoft.graph.windows10EndpointProtectionConfiguration*' { 'Endpoint Protection' } - '*microsoft.graph.windows10CustomConfiguration*' { 'Custom' } - '*microsoft.graph.windows10DeviceFirmwareConfigurationInterface*' { 'Firmware Configuration' } - '*groupPolicyConfigurations*' { 'Administrative Templates' } - '*windowsDomainJoinConfiguration*' { 'Domain Join configuration' } - '*windowsUpdateForBusinessConfiguration*' { 'Update Configuration' } - '*windowsHealthMonitoringConfiguration*' { 'Health Monitoring' } - '*microsoft.graph.macOSGeneralDeviceConfiguration*' { 'MacOS Configuration' } - '*microsoft.graph.macOSEndpointProtectionConfiguration*' { 'MacOS Endpoint Protection' } - '*microsoft.graph.androidWorkProfileGeneralDeviceConfiguration*' { 'Android Configuration' } - default { $_.'assignments@odata.context' } - } - $Assignments = $_.assignments.target | Select-Object -Property '@odata.type', groupId - $PolicyAssignment = [System.Collections.Generic.List[string]]::new() - $PolicyExclude = [System.Collections.Generic.List[string]]::new() - ForEach ($target in $Assignments) { - switch ($target.'@odata.type') { - '#microsoft.graph.allDevicesAssignmentTarget' { $PolicyAssignment.Add('All Devices') } - '#microsoft.graph.exclusionallDevicesAssignmentTarget' { $PolicyExclude.Add('All Devices') } - '#microsoft.graph.allUsersAssignmentTarget' { $PolicyAssignment.Add('All Users') } - '#microsoft.graph.allLicensedUsersAssignmentTarget' { $PolicyAssignment.Add('All Licenced Users') } - '#microsoft.graph.exclusionallUsersAssignmentTarget' { $PolicyExclude.Add('All Users') } - '#microsoft.graph.groupAssignmentTarget' { $PolicyAssignment.Add($Groups.Where({ $_.id -eq $target.groupId }).displayName) } - '#microsoft.graph.exclusionGroupAssignmentTarget' { $PolicyExclude.Add($Groups.Where({ $_.id -eq $target.groupId }).displayName) } - default { - $PolicyAssignment.Add($null) - $PolicyExclude.Add($null) - } + $URLName = $_.Id + $_.body.Value | ForEach-Object { + $policyTypeName = switch -Wildcard ($_.'assignments@odata.context') { + '*microsoft.graph.windowsIdentityProtectionConfiguration*' { 'Identity Protection' } + '*microsoft.graph.windows10EndpointProtectionConfiguration*' { 'Endpoint Protection' } + '*microsoft.graph.windows10CustomConfiguration*' { 'Custom' } + '*microsoft.graph.windows10DeviceFirmwareConfigurationInterface*' { 'Firmware Configuration' } + '*groupPolicyConfigurations*' { 'Administrative Templates' } + '*windowsDomainJoinConfiguration*' { 'Domain Join configuration' } + '*windowsUpdateForBusinessConfiguration*' { 'Update Configuration' } + '*windowsHealthMonitoringConfiguration*' { 'Health Monitoring' } + '*microsoft.graph.macOSGeneralDeviceConfiguration*' { 'MacOS Configuration' } + '*microsoft.graph.macOSEndpointProtectionConfiguration*' { 'MacOS Endpoint Protection' } + '*microsoft.graph.androidWorkProfileGeneralDeviceConfiguration*' { 'Android Configuration' } + '*windowsFeatureUpdateProfiles*' { 'Feature Update' } + default { $_.'assignments@odata.context' } + } + $Assignments = $_.assignments.target | Select-Object -Property '@odata.type', groupId + $PolicyAssignment = [System.Collections.Generic.List[string]]::new() + $PolicyExclude = [System.Collections.Generic.List[string]]::new() + ForEach ($target in $Assignments) { + switch ($target.'@odata.type') { + '#microsoft.graph.allDevicesAssignmentTarget' { $PolicyAssignment.Add('All Devices') } + '#microsoft.graph.exclusionallDevicesAssignmentTarget' { $PolicyExclude.Add('All Devices') } + '#microsoft.graph.allUsersAssignmentTarget' { $PolicyAssignment.Add('All Users') } + '#microsoft.graph.allLicensedUsersAssignmentTarget' { $PolicyAssignment.Add('All Licenced Users') } + '#microsoft.graph.exclusionallUsersAssignmentTarget' { $PolicyExclude.Add('All Users') } + '#microsoft.graph.groupAssignmentTarget' { $PolicyAssignment.Add($Groups.Where({ $_.id -eq $target.groupId }).displayName) } + '#microsoft.graph.exclusionGroupAssignmentTarget' { $PolicyExclude.Add($Groups.Where({ $_.id -eq $target.groupId }).displayName) } + default { + $PolicyAssignment.Add($null) + $PolicyExclude.Add($null) } } - if ($null -eq $_.displayname) { $_ | Add-Member -NotePropertyName displayName -NotePropertyValue $_.name } - $_ | Add-Member -NotePropertyName PolicyTypeName -NotePropertyValue $policyTypeName - $_ | Add-Member -NotePropertyName URLName -NotePropertyValue $URLName - $_ | Add-Member -NotePropertyName PolicyAssignment -NotePropertyValue ($PolicyAssignment -join ', ') - $_ | Add-Member -NotePropertyName PolicyExclude -NotePropertyValue ($PolicyExclude -join ', ') - $_ - } | Where-Object { $null -ne $_.DisplayName } - } + } + if ($null -eq $_.displayname) { $_ | Add-Member -NotePropertyName displayName -NotePropertyValue $_.name } + $_ | Add-Member -NotePropertyName PolicyTypeName -NotePropertyValue $policyTypeName + $_ | Add-Member -NotePropertyName URLName -NotePropertyValue $URLName + $_ | Add-Member -NotePropertyName PolicyAssignment -NotePropertyValue ($PolicyAssignment -join ', ') + $_ | Add-Member -NotePropertyName PolicyExclude -NotePropertyValue ($PolicyExclude -join ', ') + $_ + } | Where-Object { $null -ne $_.DisplayName } + } } # Filter the results to sort out linux scripts diff --git a/Modules/CIPPCore/Public/New-CIPPIntuneTemplate.ps1 b/Modules/CIPPCore/Public/New-CIPPIntuneTemplate.ps1 index 25595a59eb51..6b89083b332b 100644 --- a/Modules/CIPPCore/Public/New-CIPPIntuneTemplate.ps1 +++ b/Modules/CIPPCore/Public/New-CIPPIntuneTemplate.ps1 @@ -97,6 +97,12 @@ function New-CIPPIntuneTemplate { $TemplateJson = (ConvertTo-Json -InputObject $inputvar -Depth 100 -Compress) } + 'windowsFeatureUpdateProfiles' { + $Type = 'windowsFeatureUpdateProfiles' + $Template = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/$($urlname)/$($ID)" -tenantid $tenantfilter | Select-Object * -ExcludeProperty id, lastModifiedDateTime, '@odata.context', 'ScopeTagIds', 'supportsScopeTags', 'createdDateTime' + $DisplayName = $Template.displayName + $TemplateJson = ConvertTo-Json -InputObject $Template -Depth 100 -Compress + } } return [PSCustomObject]@{ TemplateJson = $TemplateJson diff --git a/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 b/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 index f44f5616fa4f..626b4dbf61da 100644 --- a/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 @@ -52,15 +52,15 @@ function Set-CIPPAssignedPolicy { } default { Write-Host "We're supposed to assign a custom group. The group is $GroupName" - $GroupNames = $GroupName.Split(',') + $GroupNames = $GroupName -split '\s,\s' $GroupIds = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/groups?$select=id,displayName&$top=999' -tenantid $TenantFilter | - ForEach-Object { - foreach ($SingleName in $GroupNames) { - if ($_.displayName -like $SingleName) { - $_.id + ForEach-Object { + foreach ($SingleName in $GroupNames) { + if ($_.displayName -like $SingleName) { + $_.id + } } } - } foreach ($gid in $GroupIds) { $assignmentsList.Add( @{ @@ -75,15 +75,15 @@ function Set-CIPPAssignedPolicy { } if ($ExcludeGroup) { Write-Host "We're supposed to exclude a custom group. The group is $ExcludeGroup" - $ExcludeGroupNames = $ExcludeGroup.Split(',') + $ExcludeGroupNames = $GroupName -split '\s,\s' $ExcludeGroupIds = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/groups?$select=id,displayName&$top=999' -tenantid $TenantFilter | - ForEach-Object { - foreach ($SingleName in $ExcludeGroupNames) { - if ($_.displayName -like $SingleName) { - $_.id + ForEach-Object { + foreach ($SingleName in $ExcludeGroupNames) { + if ($_.displayName -like $SingleName) { + $_.id + } } } - } foreach ($egid in $ExcludeGroupIds) { $assignmentsList.Add( diff --git a/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1 b/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1 index abc3941896f6..e9a6dfce7b91 100644 --- a/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1 @@ -135,6 +135,25 @@ function Set-CIPPIntunePolicy { Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenantFilter) -message "Added policy $($DisplayName) via template" -Sev 'info' } } + 'windowsFeatureUpdateProfiles' { + $PlatformType = 'deviceManagement' + $TemplateTypeURL = 'windowsFeatureUpdateProfiles' + $File = ($RawJSON | ConvertFrom-Json) + $DisplayName = $File.displayName ?? $File.Name + $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter + if ($DisplayName -in $CheckExististing.displayName) { + $PostType = 'edited' + $ExistingID = $CheckExististing | Where-Object -Property displayName -EQ $displayname + Write-Host 'We are editing' + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL/$($ExistingID.Id)" -tenantid $tenantFilter -type PUT -body $RawJSON + $CreateRequest = $CheckExististing | Where-Object -Property displayName -EQ $DisplayName + + } else { + $PostType = 'added' + $CreateRequest = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/$PlatformType/$TemplateTypeURL" -tenantid $tenantFilter -type POST -body $RawJSON + Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenantFilter) -message "Added policy $($DisplayName) via template" -Sev 'info' + } + } } Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenantFilter) -message "$($PostType) policy $($Displayname)" -Sev 'Info' From 7df20e2bcffdee2c61c941fed7eb0078dad35a76 Mon Sep 17 00:00:00 2001 From: Esco Date: Fri, 28 Feb 2025 09:52:30 +0100 Subject: [PATCH 089/167] fix: fix broken assignment * ExcludeGroupNames wrong variable * -split '\s,\s' made $AssignJSON NULL --- Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 b/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 index 626b4dbf61da..a719998ee3fe 100644 --- a/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPAssignedPolicy.ps1 @@ -52,7 +52,7 @@ function Set-CIPPAssignedPolicy { } default { Write-Host "We're supposed to assign a custom group. The group is $GroupName" - $GroupNames = $GroupName -split '\s,\s' + $GroupNames = $GroupName.Split(',').Trim() $GroupIds = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/groups?$select=id,displayName&$top=999' -tenantid $TenantFilter | ForEach-Object { foreach ($SingleName in $GroupNames) { @@ -75,7 +75,7 @@ function Set-CIPPAssignedPolicy { } if ($ExcludeGroup) { Write-Host "We're supposed to exclude a custom group. The group is $ExcludeGroup" - $ExcludeGroupNames = $GroupName -split '\s,\s' + $ExcludeGroupNames = $ExcludeGroup.Split(',').Trim() $ExcludeGroupIds = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/groups?$select=id,displayName&$top=999' -tenantid $TenantFilter | ForEach-Object { foreach ($SingleName in $ExcludeGroupNames) { From 0ccc1d74bdce98c38d2f4ebea1117882aa67b748 Mon Sep 17 00:00:00 2001 From: Esco Date: Fri, 28 Feb 2025 11:58:18 +0100 Subject: [PATCH 090/167] fix: corrected policy name variable --- .../Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 index c597958af7cf..a5fe3e775c3e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 @@ -37,7 +37,6 @@ function Invoke-CIPPStandardIntuneTemplate { Write-Host 'starting template deploy' Write-Host "The full settings are $($Settings | ConvertTo-Json)" - $APINAME = 'Standards' foreach ($Template in $Settings) { Write-Host "working on template deploy: $($Template | ConvertTo-Json)" try { @@ -53,7 +52,7 @@ function Invoke-CIPPStandardIntuneTemplate { } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create or update Intune Template $PolicyName, Error: $ErrorMessage" -sev 'Error' + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create or update Intune Template $displayname, Error: $ErrorMessage" -sev 'Error' } } } From 0fe1a3fb50c8b629aafc38cf7b6bd82c5cd38f89 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Fri, 28 Feb 2025 14:39:33 +0100 Subject: [PATCH 091/167] update for esco --- Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1 | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1 b/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1 index e9a6dfce7b91..173a37b874a9 100644 --- a/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPIntunePolicy.ps1 @@ -11,6 +11,22 @@ function Set-CIPPIntunePolicy { $APINAME, $tenantFilter ) + #connect to table, get replacement map. This is for future usage. The replacement map will allow users to create custom vars that get replaced by the actual values per tenant. Example: + # %WallPaperPath% gets replaced by RowKey WallPaperPath which is set to C:\Wallpapers for tenant 1, and D:\Wallpapers for tenant 2 + $ReplaceTable = Get-CIPPTable -tablename 'CippReplacemap' + $ReplaceMap = Get-CIPPAzDataTableEntity @ReplaceTable -Filter "PartitionKey eq '$tenantFilter'" + if ($ReplaceMap) { + foreach ($Replace in $ReplaceMap) { + $RawJSON = $RawJSON -replace $Replace.RowKey, $Replace.Value + } + } + #default replacements for all tenants: %tenantid% becomes $tenant.customerId, %tenantfilter% becomes $tenant.defaultDomainName, %tenantname% becomes $tenant.displayName + $Tenant = Get-Tenants -TenantFilter $tenantFilter + $RawJSON = $RawJSON -replace '%tenantid%', $Tenant.customerId + $RawJSON = $RawJSON -replace '%tenantfilter%', $Tenant.defaultDomainName + $RawJSON = $RawJSON -replace '%tenantname%', $Tenant.displayName + + try { switch ($TemplateType) { 'AppProtection' { From 83ef8b277422829ba38e05c246a64a230655d59d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Fri, 28 Feb 2025 15:06:33 +0100 Subject: [PATCH 092/167] Make command more aggressive --- .../Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 index d9eb6ad3817f..82a9e84a310c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 @@ -14,13 +14,12 @@ Function Invoke-ExecStartManagedFolderAssistant { $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. $Tenant = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter $ID = $Request.Query.ID ?? $Request.Body.ID try { - $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Start-ManagedFolderAssistant' -cmdParams @{Identity = $ID } + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Start-ManagedFolderAssistant' -cmdParams @{Identity = $ID; AggMailboxCleanup = $true; FullCrawl = $true } $Result = "Successfully started Managed Folder Assistant for mailbox $($ID)." $Severity = 'Info' $StatusCode = [HttpStatusCode]::OK @@ -31,7 +30,6 @@ Function Invoke-ExecStartManagedFolderAssistant { $StatusCode = [HttpStatusCode]::InternalServerError } finally { Write-LogMessage -Headers $Headers -API $APIName -tenant $Tenant -message $Result -Sev $Severity -LogData $ErrorMessage - } $Body = [pscustomobject] @{ 'Results' = $Result } From c42cba7f1ec57fefd363339fd96fc1d496735635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Fri, 28 Feb 2025 15:06:33 +0100 Subject: [PATCH 093/167] Make command more aggressive --- .../Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 index d9eb6ad3817f..82a9e84a310c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 @@ -14,13 +14,12 @@ Function Invoke-ExecStartManagedFolderAssistant { $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. $Tenant = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter $ID = $Request.Query.ID ?? $Request.Body.ID try { - $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Start-ManagedFolderAssistant' -cmdParams @{Identity = $ID } + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Start-ManagedFolderAssistant' -cmdParams @{Identity = $ID; AggMailboxCleanup = $true; FullCrawl = $true } $Result = "Successfully started Managed Folder Assistant for mailbox $($ID)." $Severity = 'Info' $StatusCode = [HttpStatusCode]::OK @@ -31,7 +30,6 @@ Function Invoke-ExecStartManagedFolderAssistant { $StatusCode = [HttpStatusCode]::InternalServerError } finally { Write-LogMessage -Headers $Headers -API $APIName -tenant $Tenant -message $Result -Sev $Severity -LogData $ErrorMessage - } $Body = [pscustomobject] @{ 'Results' = $Result } From afd27fd4c9b2c66220ccc3f9633c67e2d7d1d3a4 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Fri, 28 Feb 2025 10:23:27 -0500 Subject: [PATCH 094/167] fix: scheduled task logging --- .../Push-ExecScheduledCommand.ps1 | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 index abd5936d6f0d..460ea3456778 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 @@ -10,6 +10,8 @@ function Push-ExecScheduledCommand { $Table = Get-CippTable -tablename 'ScheduledTasks' $task = $Item.TaskInfo $commandParameters = $Item.Parameters | ConvertTo-Json -Depth 10 | ConvertFrom-Json -AsHashtable + $Tenant = $Item.Parameters.TenantFilter ?? $Item.TaskInfo.Tenant + $TenantInfo = Get-Tenants -TenantFilter $Tenant $Function = Get-Command -Name $Item.Command if ($null -eq $Function) { @@ -21,7 +23,7 @@ function Push-ExecScheduledCommand { Results = "$Results" TaskState = $State } - Write-LogMessage -API 'Scheduler_UserTasks' -tenant $tenant -message "Failed to execute task $($task.Name): The command $($Item.Command) does not exist." -sev Error + Write-LogMessage -API 'Scheduler_UserTasks' -tenant $Tenant -tenantid $TenantInfo.customerId -message "Failed to execute task $($task.Name): The command $($Item.Command) does not exist." -sev Error return } @@ -40,8 +42,7 @@ function Push-ExecScheduledCommand { Write-Host "Failed to remove parameters: $($_.Exception.Message)" } - $tenant = $Item.Parameters.TenantFilter ?? $Item.Tenant - Write-Host "Started Task: $($Item.Command) for tenant: $tenant" + Write-Host "Started Task: $($Item.Command) for tenant: $Tenant" try { try { @@ -85,27 +86,27 @@ function Push-ExecScheduledCommand { Results = "$errorMessage" TaskState = $State } - Write-LogMessage -API 'Scheduler_UserTasks' -tenant $tenant -message "Failed to execute task $($task.Name): $errorMessage" -sev Error -LogData (Get-CippExceptionData -Exception $_.Exception) + Write-LogMessage -API 'Scheduler_UserTasks' -tenant $Tenant -tenantid $TenantInfo.customerId -message "Failed to execute task $($task.Name): $errorMessage" -sev Error -LogData (Get-CippExceptionData -Exception $_.Exception) } Write-Host 'Sending task results to target. Updating the task state.' if ($Results) { $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 - $tenant - $($task.Name)" + $HTML = $FinalResults -replace '
    ', "This alert is for tenant $Tenant.

    $TableDesign
    " | Out-String + $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 -TenantFilter $tenant } - '*email*' { Send-CIPPAlert -Type 'email' -Title $title -HTMLContent $HTML -TenantFilter $tenant } + '*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 + 'Tenant' = $Tenant 'TaskInfo' = $Item.TaskInfo 'Results' = $Results } - Send-CIPPAlert -Type 'webhook' -Title $title -TenantFilter $tenant -JSONContent $($Webhook | ConvertTo-Json -Depth 20) + Send-CIPPAlert -Type 'webhook' -Title $title -TenantFilter $Tenant -JSONContent $($Webhook | ConvertTo-Json -Depth 20) } } } @@ -149,6 +150,6 @@ function Push-ExecScheduledCommand { } } if ($TaskType -ne 'Alert') { - Write-LogMessage -API 'Scheduler_UserTasks' -tenant $tenant -message "Successfully executed task: $($task.Name)" -sev Info + Write-LogMessage -API 'Scheduler_UserTasks' -tenant $Tenant -tenantid $TenantInfo.customerId -message "Successfully executed task: $($task.Name)" -sev Info } } From 886739c8d8da971236e9372ecb4df407eba67b9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Fri, 28 Feb 2025 16:31:38 +0100 Subject: [PATCH 095/167] Use ExchangeGUID by default but allow UPN too. Fixes starting MFA if the user has a personal MS account --- .../Invoke-ExecStartManagedFolderAssistant.ps1 | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 index 82a9e84a310c..6a03af82ed65 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 @@ -16,16 +16,26 @@ Function Invoke-ExecStartManagedFolderAssistant { # Interact with query parameters or the body of the request. $Tenant = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter - $ID = $Request.Query.ID ?? $Request.Body.ID + $ID = $Request.Query.Id ?? $Request.Body.Id + $UserPrincipalName = $Request.Body.UserPrincipalName + $Identity = $ID ?? $UserPrincipalName + $ShownName = $UserPrincipalName ?? $ID + + + $ExoParams = @{ + Identity = $Identity + AggMailboxCleanup = $true + FullCrawl = $true + } try { - $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Start-ManagedFolderAssistant' -cmdParams @{Identity = $ID; AggMailboxCleanup = $true; FullCrawl = $true } - $Result = "Successfully started Managed Folder Assistant for mailbox $($ID)." + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Start-ManagedFolderAssistant' -cmdParams $ExoParams + $Result = "Successfully started Managed Folder Assistant for mailbox $($ShownName)." $Severity = 'Info' $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - $Result = "Failed to start Managed Folder Assistant for mailbox $($ID). Error: $($ErrorMessage.NormalizedError)" + $Result = "Failed to start Managed Folder Assistant for mailbox $($ShownName). Error: $($ErrorMessage.NormalizedError)" $Severity = 'Error' $StatusCode = [HttpStatusCode]::InternalServerError } finally { From f133b1dd5fdb8ab6d0deae30e41c7e3b24acf921 Mon Sep 17 00:00:00 2001 From: Kiyo Akaiwa Date: Fri, 28 Feb 2025 12:20:28 -0500 Subject: [PATCH 096/167] Fixed error - You can only set email address that belongs to your organization in report submission policy Identity:"DefaultReportSubmissionPolicy". --- .../Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 index 979a6d76d7ef..aac6b135b896 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 @@ -106,8 +106,11 @@ function Invoke-CIPPStandardUserSubmissions { $PolicyParams = @{ EnableReportToMicrosoft = $true ReportJunkToCustomizedAddress = $false + ReportJunkAddresses = $null ReportNotJunkToCustomizedAddress = $false + ReportNotJunkAddresses = $null ReportPhishToCustomizedAddress = $false + ReportPhishAddresses = $null } } else { $PolicyParams = @{ From 0daf962954ef17cc3e4bccbc6ded3121f51b6d8f Mon Sep 17 00:00:00 2001 From: John Duprey Date: Fri, 28 Feb 2025 15:29:11 -0500 Subject: [PATCH 097/167] fix: offboarding wizard casing --- Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 b/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 index c39c7879be09..029c2c11c4cb 100644 --- a/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 +++ b/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 @@ -1,4 +1,3 @@ - function Invoke-CIPPOffboardingJob { [CmdletBinding()] param ( @@ -56,14 +55,14 @@ function Invoke-CIPPOffboardingJob { { $_.RemoveLicenses -eq $true } { Remove-CIPPLicense -userid $userid -username $Username -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName -Schedule } - { $_.deleteuser -eq $true } { + { $_.DeleteUser -eq $true } { Remove-CIPPUser -userid $userid -username $Username -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName } - { $_.removeRules -eq $true } { + { $_.RemoveRules -eq $true } { Write-Host "Removing rules for $username" Remove-CIPPMailboxRule -userid $userid -username $Username -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName -RemoveAllRules } - { $_.removeMobile -eq $true } { + { $_.RemoveMobile -eq $true } { Remove-CIPPMobileDevice -userid $userid -username $Username -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName } { $_.removeCalendarInvites -eq $true } { From cae65c446ef14745ff7a26a837480a0bfec36bce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Fri, 28 Feb 2025 20:19:35 +0100 Subject: [PATCH 098/167] feat: add logging for API access in multiple functions and move some files more better move files Move and/or update email endpoints Move and/or update email endpoints Move more endpoints --- .../CIPP/Core/Invoke-ExecAddAlert.ps1 | 8 +- .../CIPP/Core/Invoke-ExecAzBobbyTables.ps1 | 4 + .../CIPP/Core/Invoke-ExecCPVRefresh.ps1 | 9 +- .../CIPP/Core/Invoke-ExecCippFunction.ps1 | 6 +- .../CIPP/Core/Invoke-ExecDurableFunctions.ps1 | 5 +- .../CIPP/Core/Invoke-ExecEditTemplate.ps1 | 3 +- .../CIPP/Core/Invoke-ExecGeoIPLookup.ps1 | 4 +- .../CIPP/Core/Invoke-ExecGraphRequest.ps1 | 189 +++++++++--------- .../CIPP/Core/Invoke-ExecPartnerWebhook.ps1 | 6 +- .../Core/Invoke-ExecServicePrincipals.ps1 | 4 + .../Core/Invoke-ExecSetCIPPAutoBackup.ps1 | 5 + .../CIPP/Core/Invoke-GetCippAlerts.ps1 | 4 + .../CIPP/Core/Invoke-GetVersion.ps1 | 3 +- .../CIPP/Core/Invoke-ListApiTest.ps1 | 4 + .../CIPP/Core/Invoke-ListGraphBulkRequest.ps1 | 16 +- .../CIPP/Core/Invoke-ListGraphRequest.ps1 | 4 +- .../CIPP/Core/invoke-ListEmptyResults.ps1 | 3 + .../Invoke-ExecExtensionMapping.ps1 | 54 ++--- .../Extensions/Invoke-ExecExtensionSync.ps1 | 3 +- .../Extensions/Invoke-ExecExtensionTest.ps1 | 6 +- .../Invoke-ExecExtensionsConfig.ps1 | 11 +- .../Extensions/Invoke-ListExtensionSync.ps1 | 2 +- .../CIPP/Setup/Invoke-ExecSAMSetup.ps1 | 4 +- .../Administration/Invoke-AddContact.ps1 | 53 +++++ .../Invoke-AddSharedMailbox.ps1 | 83 ++++++++ .../Invoke-EditContact.ps1 | 13 +- .../Invoke-ExecConvertMailbox.ps1 | 0 .../Invoke-ExecCopyForSent.ps1 | 0 .../Invoke-ExecEditCalendarPermissions.ps1 | 0 .../Invoke-ExecEditMailboxPermissions.ps1 | 0 .../Invoke-ExecEmailForward.ps1 | 0 .../Invoke-ExecEnableArchive.ps1 | 0 .../Invoke-ExecGroupsDelete.ps1 | 0 .../Invoke-ExecGroupsDeliveryManagement.ps1 | 0 .../Invoke-ExecGroupsHideFromGAL.ps1 | 0 .../Invoke-ExecHideFromGAL.ps1 | 0 .../Invoke-ExecMailboxMobileDevices.ps1 | 4 - .../Invoke-ExecRemoveMailboxRule.ps1 | 0 .../Invoke-ExecSetMailboxLocale.ps1 | 0 .../Invoke-ExecSetMailboxQuota.ps1 | 0 .../Invoke-ExecSetOoO.ps1 | 4 +- ...Invoke-ExecStartManagedFolderAssistant.ps1 | 0 .../Invoke-ListCalendarPermissions.ps1 | 0 .../Invoke-ListContacts.ps1 | 0 .../Invoke-ListMailboxMobileDevices.ps1 | 0 .../Invoke-ListMailboxRules.ps1 | 0 .../Invoke-ListMailboxes.ps1 | 4 - .../{ => Administration}/Invoke-ListOoO.ps1 | 2 +- .../Invoke-ListSharedMailboxStatistics.ps1 | 0 .../Invoke-ListmailboxPermissions.ps1 | 0 .../Administration}/Invoke-RemoveContact.ps1 | 0 .../Email-Exchange/Invoke-AddContact.ps1 | 48 ----- .../Email-Exchange/Invoke-AddExConnector.ps1 | 38 ---- .../Invoke-AddSharedMailbox.ps1 | 83 -------- .../Invoke-AddSpamFilterTemplate.ps1 | 53 ----- .../Invoke-ListAntiPhishingFilters.ps1 | 3 +- .../Reports/Invoke-ListGlobalAddressList.ps1 | 3 +- .../Reports/Invoke-ListMailboxCAS.ps1 | 6 +- .../Reports/Invoke-ListMalwareFilters.ps1 | 5 +- .../Invoke-ListSafeAttachmentsFilters.ps1 | 3 +- .../Reports/Invoke-ListSafeLinksFilters.ps1 | 3 +- ...Invoke-ListSharedMailboxAccountEnabled.ps1 | 3 +- .../{ => Resources}/Invoke-AddRoomMailbox.ps1 | 23 ++- .../Invoke-EditRoomMailbox.ps1 | 0 .../{ => Resources}/Invoke-ListRoomLists.ps1 | 0 .../{ => Resources}/Invoke-ListRooms.ps1 | 0 .../{ => Spamfilter}/Invoke-AddSpamFilter.ps1 | 20 +- .../Invoke-AddSpamFilterTemplate.ps1 | 53 +++++ .../Invoke-AddTenantAllowBlockList.ps1 | 21 +- .../Invoke-EditAntiPhishingFilter.ps1 | 114 +++++------ .../Invoke-EditMalwareFilter.ps1 | 114 +++++------ .../Invoke-EditSafeAttachmentsFilter.ps1 | 114 +++++------ .../Invoke-EditSafeLinksFilter.ps1 | 114 +++++------ .../Invoke-EditSpamFilter.ps1 | 0 .../Invoke-ExecQuarantineManagement.ps1 | 0 .../Invoke-ListConnectionFilter.ps1 | 0 .../Invoke-ListConnectionFilterTemplates.ps1 | 0 .../Invoke-ListMailQuarantine.ps1 | 0 .../Invoke-ListMailQuarantineMessage.ps1 | 0 .../Invoke-ListSpamFilterTemplates.ps1 | 0 .../Invoke-ListSpamfilter.ps1 | 0 .../Invoke-RemoveConnectionfilterTemplate.ps1 | 0 .../Spamfilter}/Invoke-RemoveSpamfilter.ps1 | 0 .../Invoke-RemoveSpamfilterTemplate.ps1 | 0 .../{ => Tools}/Invoke-ExecMailTest.ps1 | 3 - .../{ => Tools}/Invoke-ExecMailboxRestore.ps1 | 3 +- .../{ => Tools}/Invoke-ListExoRequest.ps1 | 0 .../Tools}/Invoke-ListMailboxRestores.ps1 | 0 .../{ => Tools}/Invoke-ListMessageTrace.ps1 | 4 + .../Invoke-AddConnectionFilter.ps1 | 4 +- .../Invoke-AddConnectionFilterTemplate.ps1 | 26 +-- .../Transport/Invoke-AddExConnector.ps1 | 40 ++++ .../Invoke-AddExConnectorTemplate.ps1 | 34 ++-- .../Invoke-AddTransportRule.ps1 | 0 .../Invoke-AddTransportTemplate.ps1 | 0 .../Invoke-EditExConnector.ps1 | 0 .../Invoke-EditTransportRule.ps1 | 0 .../Invoke-ListExConnectorTemplates.ps1 | 0 .../Invoke-ListExchangeConnectors.ps1 | 0 .../Invoke-ListTransportRules.ps1 | 0 .../Invoke-ListTransportRulesTemplates.ps1 | 0 .../Transport}/Invoke-RemoveExConnector.ps1 | 0 .../Invoke-RemoveExConnectorTemplate.ps1 | 0 .../Transport}/Invoke-RemoveTransportRule.ps1 | 0 .../Invoke-RemoveTransportRuleTemplate.ps1 | 0 .../MEM}/Invoke-ListDefenderState.ps1 | 0 .../Endpoint/MEM}/Invoke-ListDefenderTVM.ps1 | 0 .../Endpoint/MEM}/Invoke-ListIntunePolicy.ps1 | 0 .../MEM}/Invoke-ListIntuneTemplates.ps1 | 0 .../MEM}/Invoke-RemoveIntuneTemplate.ps1 | 0 .../Endpoint/MEM}/Invoke-RemovePolicy.ps1 | 0 .../Groups}/Invoke-ListGroupTemplates.ps1 | 0 .../Groups}/Invoke-RemoveGroupTemplate.ps1 | 0 .../Users}/Invoke-CIPPOffboardingJob.ps1 | 0 .../Users}/Invoke-RemoveUser.ps1 | 0 .../Invoke-ListSharepointQuota.ps1 | 0 .../Administration}/Invoke-ListDomains.ps1 | 0 .../Conditional}/Invoke-RemoveCAPolicy.ps1 | 0 .../Conditional}/Invoke-RemoveCATemplate.ps1 | 0 .../Reports}/Invoke-ListServiceHealth.ps1 | 0 .../Standards}/Invoke-CIPPStandardsRun.ps1 | 0 .../Standards}/Invoke-ListStandards.ps1 | 0 .../Standards}/Invoke-RemoveBPATemplate.ps1 | 0 .../Standards}/Invoke-RemoveStandard.ps1 | 0 .../Invoke-RemoveStandardTemplate.ps1 | 0 125 files changed, 765 insertions(+), 690 deletions(-) create mode 100644 Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-AddContact.ps1 create mode 100644 Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-AddSharedMailbox.ps1 rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-EditContact.ps1 (87%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ExecConvertMailbox.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ExecCopyForSent.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ExecEditCalendarPermissions.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ExecEditMailboxPermissions.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ExecEmailForward.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ExecEnableArchive.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ExecGroupsDelete.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ExecGroupsDeliveryManagement.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ExecGroupsHideFromGAL.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ExecHideFromGAL.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ExecMailboxMobileDevices.ps1 (90%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ExecRemoveMailboxRule.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ExecSetMailboxLocale.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ExecSetMailboxQuota.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ExecSetOoO.ps1 (97%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ExecStartManagedFolderAssistant.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ListCalendarPermissions.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ListContacts.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Email-Exchange/Administration}/Invoke-ListMailboxMobileDevices.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Email-Exchange/Administration}/Invoke-ListMailboxRules.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ListMailboxes.ps1 (96%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Administration}/Invoke-ListOoO.ps1 (92%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Email-Exchange/Administration}/Invoke-ListSharedMailboxStatistics.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Email-Exchange/Administration}/Invoke-ListmailboxPermissions.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Email-Exchange/Administration}/Invoke-RemoveContact.ps1 (100%) delete mode 100644 Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddContact.ps1 delete mode 100644 Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddExConnector.ps1 delete mode 100644 Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSharedMailbox.ps1 delete mode 100644 Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSpamFilterTemplate.ps1 rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Resources}/Invoke-AddRoomMailbox.ps1 (68%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Resources}/Invoke-EditRoomMailbox.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Resources}/Invoke-ListRoomLists.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Resources}/Invoke-ListRooms.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Spamfilter}/Invoke-AddSpamFilter.ps1 (52%) create mode 100644 Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-AddSpamFilterTemplate.ps1 rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Spamfilter}/Invoke-AddTenantAllowBlockList.ps1 (64%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Spamfilter}/Invoke-EditAntiPhishingFilter.ps1 (97%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Spamfilter}/Invoke-EditMalwareFilter.ps1 (97%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Spamfilter}/Invoke-EditSafeAttachmentsFilter.ps1 (97%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Spamfilter}/Invoke-EditSafeLinksFilter.ps1 (97%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Spamfilter}/Invoke-EditSpamFilter.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Spamfilter}/Invoke-ExecQuarantineManagement.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Spamfilter}/Invoke-ListConnectionFilter.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Spamfilter}/Invoke-ListConnectionFilterTemplates.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Spamfilter}/Invoke-ListMailQuarantine.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Spamfilter}/Invoke-ListMailQuarantineMessage.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Spamfilter}/Invoke-ListSpamFilterTemplates.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Spamfilter}/Invoke-ListSpamfilter.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Email-Exchange/Spamfilter}/Invoke-RemoveConnectionfilterTemplate.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Email-Exchange/Spamfilter}/Invoke-RemoveSpamfilter.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Email-Exchange/Spamfilter}/Invoke-RemoveSpamfilterTemplate.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Tools}/Invoke-ExecMailTest.ps1 (97%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Tools}/Invoke-ExecMailboxRestore.ps1 (97%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Tools}/Invoke-ListExoRequest.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Email-Exchange/Tools}/Invoke-ListMailboxRestores.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Tools}/Invoke-ListMessageTrace.ps1 (95%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Transport}/Invoke-AddConnectionFilter.ps1 (91%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Transport}/Invoke-AddConnectionFilterTemplate.ps1 (65%) create mode 100644 Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-AddExConnector.ps1 rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Transport}/Invoke-AddExConnectorTemplate.ps1 (63%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Transport}/Invoke-AddTransportRule.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Transport}/Invoke-AddTransportTemplate.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Transport}/Invoke-EditExConnector.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Transport}/Invoke-EditTransportRule.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Email-Exchange/Transport}/Invoke-ListExConnectorTemplates.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Transport}/Invoke-ListExchangeConnectors.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Transport}/Invoke-ListTransportRules.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/{ => Transport}/Invoke-ListTransportRulesTemplates.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Email-Exchange/Transport}/Invoke-RemoveExConnector.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Email-Exchange/Transport}/Invoke-RemoveExConnectorTemplate.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Email-Exchange/Transport}/Invoke-RemoveTransportRule.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Email-Exchange/Transport}/Invoke-RemoveTransportRuleTemplate.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Endpoint/MEM}/Invoke-ListDefenderState.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Endpoint/MEM}/Invoke-ListDefenderTVM.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Endpoint/MEM}/Invoke-ListIntunePolicy.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Endpoint/MEM}/Invoke-ListIntuneTemplates.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Endpoint/MEM}/Invoke-RemoveIntuneTemplate.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Endpoint/MEM}/Invoke-RemovePolicy.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Identity/Administration/Groups}/Invoke-ListGroupTemplates.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Identity/Administration/Groups}/Invoke-RemoveGroupTemplate.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Identity/Administration/Users}/Invoke-CIPPOffboardingJob.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Identity/Administration/Users}/Invoke-RemoveUser.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Teams-Sharepoint}/Invoke-ListSharepointQuota.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Tenant/Administration}/Invoke-ListDomains.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Tenant/Conditional}/Invoke-RemoveCAPolicy.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Tenant/Conditional}/Invoke-RemoveCATemplate.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Tenant/Reports}/Invoke-ListServiceHealth.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Tenant/Standards}/Invoke-CIPPStandardsRun.ps1 (100%) rename Modules/CIPPCore/Public/Entrypoints/{ => HTTP Functions/Tenant/Standards}/Invoke-ListStandards.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Tenant/Standards}/Invoke-RemoveBPATemplate.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Tenant/Standards}/Invoke-RemoveStandard.ps1 (100%) rename Modules/CIPPCore/Public/{ => Entrypoints/HTTP Functions/Tenant/Standards}/Invoke-RemoveStandardTemplate.ps1 (100%) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecAddAlert.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecAddAlert.ps1 index 4d59debe39f5..0de78563a5e8 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecAddAlert.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecAddAlert.ps1 @@ -10,6 +10,10 @@ Function Invoke-ExecAddAlert { [CmdletBinding()] param($Request, $TriggerMetadata) + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $Severity = 'Alert' $Result = if ($Request.Body.sendEmailNow -or $Request.Body.sendWebhookNow -eq $true -or $Request.Body.writeLog -eq $true) { @@ -35,11 +39,11 @@ Function Invoke-ExecAddAlert { Send-CIPPAlert @CIPPAlert } if ($Request.Body.writeLog) { - Write-LogMessage -headers $Request.Headers -API 'Alerts' -message $Request.Body.text -Sev $Severity + Write-LogMessage -headers $Headers -API 'Alerts' -message $Request.Body.text -Sev $Severity 'Successfully generated alert.' } } else { - Write-LogMessage -headers $Request.Headers -API 'Alerts' -message $Request.Body.text -Sev $Severity + Write-LogMessage -headers $Headers -API 'Alerts' -message $Request.Body.text -Sev $Severity 'Successfully generated alert.' } Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecAzBobbyTables.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecAzBobbyTables.ps1 index 88080bdcf5b4..ecde857f328d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecAzBobbyTables.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecAzBobbyTables.ps1 @@ -13,6 +13,10 @@ function Invoke-ExecAzBobbyTables { [CmdletBinding()] param($Request, $TriggerMetadata) + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $AllowList = @( 'Add-AzDataTableEntity' 'Update-AzDataTableEntity' diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecCPVRefresh.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecCPVRefresh.ps1 index dbf1d9de62de..972d03b87485 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecCPVRefresh.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecCPVRefresh.ps1 @@ -10,10 +10,11 @@ function Invoke-ExecCPVRefresh { CIPP.Core.ReadWrite #> [CmdletBinding()] - param( - $Request, - $TriggerMetadata - ) + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' $InstanceId = Start-UpdatePermissionsOrchestrator diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecCippFunction.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecCippFunction.ps1 index a7f4e599579b..5ed10829e631 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecCippFunction.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecCippFunction.ps1 @@ -12,6 +12,10 @@ function Invoke-ExecCippFunction { [CmdletBinding()] param($Request, $TriggerMetadata) + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $BlockList = @( 'Get-GraphToken' 'Get-GraphTokenFromCert' @@ -45,4 +49,4 @@ function Invoke-ExecCippFunction { StatusCode = $StatusCode Body = $Results }) -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecDurableFunctions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecDurableFunctions.ps1 index 484bc24dab25..4cbfcda3b49d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecDurableFunctions.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecDurableFunctions.ps1 @@ -8,8 +8,9 @@ function Invoke-ExecDurableFunctions { [CmdletBinding(SupportsShouldProcess = $true)] param($Request, $TriggerMetadata) - $APIName = 'ExecDurableStats' - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' # Collect info $StorageContext = New-AzStorageContext -ConnectionString $env:AzureWebJobsStorage diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecEditTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecEditTemplate.ps1 index 2cf918816be6..c0e78d9f845c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecEditTemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecEditTemplate.ps1 @@ -11,7 +11,8 @@ Function Invoke-ExecEditTemplate { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' try { $Table = Get-CippTable -tablename 'templates' diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecGeoIPLookup.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecGeoIPLookup.ps1 index 0cf94d30d806..45a616403714 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecGeoIPLookup.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecGeoIPLookup.ps1 @@ -11,7 +11,9 @@ Function Invoke-ExecGeoIPLookup { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $IP = $Request.Query.IP ?? $Request.Body.IP if (-not $IP) { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecGraphRequest.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecGraphRequest.ps1 index dec61d0e5b25..d06367943d64 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecGraphRequest.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecGraphRequest.ps1 @@ -1,111 +1,112 @@ using namespace System.Net Function Invoke-ExecGraphRequest { - <# + <# .FUNCTIONALITY Entrypoint #> - [CmdletBinding()] - param($Request, $TriggerMetadata) + [CmdletBinding()] + param($Request, $TriggerMetadata) - $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - Function ConvertTo-FlatObject { - # https://evotec.xyz/powershell-converting-advanced-object-to-flat-object/ - MIT License - [CmdletBinding()] - Param ( - [Parameter(ValueFromPipeLine)][Object[]]$Objects, - [String]$Separator = '.', - [ValidateSet('', 0, 1)]$Base = 1, - [int]$Depth = 5, - [Parameter(DontShow)][String[]]$Path, - [Parameter(DontShow)][System.Collections.IDictionary] $OutputObject - ) - Begin { - $InputObjects = [System.Collections.Generic.List[Object]]::new() - } - Process { - foreach ($O in $Objects) { - $InputObjects.Add($O) + Function ConvertTo-FlatObject { + # https://evotec.xyz/powershell-converting-advanced-object-to-flat-object/ - MIT License + [CmdletBinding()] + Param ( + [Parameter(ValueFromPipeLine)][Object[]]$Objects, + [String]$Separator = '.', + [ValidateSet('', 0, 1)]$Base = 1, + [int]$Depth = 5, + [Parameter(DontShow)][String[]]$Path, + [Parameter(DontShow)][System.Collections.IDictionary] $OutputObject + ) + Begin { + $InputObjects = [System.Collections.Generic.List[Object]]::new() + } + Process { + foreach ($O in $Objects) { + $InputObjects.Add($O) + } + } + End { + If ($PSBoundParameters.ContainsKey('OutputObject')) { + $Object = $InputObjects[0] + $Iterate = [ordered] @{} + if ($null -eq $Object) { + #Write-Verbose -Message "ConvertTo-FlatObject - Object is null" + } elseif ($Object.GetType().Name -in 'String', 'DateTime', 'TimeSpan', 'Version', 'Enum') { + $Object = $Object.ToString() + } elseif ($Depth) { + $Depth-- + If ($Object -is [System.Collections.IDictionary]) { + $Iterate = $Object + } elseif ($Object -is [Array] -or $Object -is [System.Collections.IEnumerable]) { + $i = $Base + foreach ($Item in $Object.GetEnumerator()) { + $Iterate["$i"] = $Item + $i += 1 } - } - End { - If ($PSBoundParameters.ContainsKey('OutputObject')) { - $Object = $InputObjects[0] - $Iterate = [ordered] @{} - if ($null -eq $Object) { - #Write-Verbose -Message "ConvertTo-FlatObject - Object is null" - } elseif ($Object.GetType().Name -in 'String', 'DateTime', 'TimeSpan', 'Version', 'Enum') { - $Object = $Object.ToString() - } elseif ($Depth) { - $Depth-- - If ($Object -is [System.Collections.IDictionary]) { - $Iterate = $Object - } elseif ($Object -is [Array] -or $Object -is [System.Collections.IEnumerable]) { - $i = $Base - foreach ($Item in $Object.GetEnumerator()) { - $Iterate["$i"] = $Item - $i += 1 - } - } else { - foreach ($Prop in $Object.PSObject.Properties) { - if ($Prop.IsGettable) { - $Iterate["$($Prop.Name)"] = $Object.$($Prop.Name) - } - } - } - } - If ($Iterate.Keys.Count) { - foreach ($Key in $Iterate.Keys) { - ConvertTo-FlatObject -Objects @(, $Iterate["$Key"]) -Separator $Separator -Base $Base -Depth $Depth -Path ($Path + $Key) -OutputObject $OutputObject - } - } else { - $Property = $Path -Join $Separator - $OutputObject[$Property] = $Object - } - } elseif ($InputObjects.Count -gt 0) { - foreach ($ItemObject in $InputObjects) { - $OutputObject = [ordered]@{} - ConvertTo-FlatObject -Objects @(, $ItemObject) -Separator $Separator -Base $Base -Depth $Depth -Path $Path -OutputObject $OutputObject - [PSCustomObject] $OutputObject - } + } else { + foreach ($Prop in $Object.PSObject.Properties) { + if ($Prop.IsGettable) { + $Iterate["$($Prop.Name)"] = $Object.$($Prop.Name) + } } + } } - } - $TenantFilter = $Request.Query.TenantFilter - try { - if ($TenantFilter -ne 'AllTenants') { - $RawGraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/$($Request.Query.Endpoint)" -tenantid $TenantFilter -NoPagination [boolean]$Request.query.DisablePagination -ComplexFilter + If ($Iterate.Keys.Count) { + foreach ($Key in $Iterate.Keys) { + ConvertTo-FlatObject -Objects @(, $Iterate["$Key"]) -Separator $Separator -Base $Base -Depth $Depth -Path ($Path + $Key) -OutputObject $OutputObject + } } else { - $RawGraphRequest = Get-Tenants | ForEach-Object -Parallel { - Import-Module '.\Modules\AzBobbyTables' - Import-Module '.\Modules\CIPPCore' - try { - $DefaultDomainName = $_.defaultDomainName - $TenantName = $_.displayName - New-GraphGetRequest -uri "https://graph.microsoft.com/beta/$($using:Request.Query.Endpoint)" -tenantid $DefaultDomainName -NoPagination [boolean]$using:Request.query.DisablePagination -ComplexFilter | Select-Object @{ - label = 'Tenant' - expression = { $TenantName } - }, * - } catch { - continue - } - } - + $Property = $Path -Join $Separator + $OutputObject[$Property] = $Object + } + } elseif ($InputObjects.Count -gt 0) { + foreach ($ItemObject in $InputObjects) { + $OutputObject = [ordered]@{} + ConvertTo-FlatObject -Objects @(, $ItemObject) -Separator $Separator -Base $Base -Depth $Depth -Path $Path -OutputObject $OutputObject + [PSCustomObject] $OutputObject } - $GraphRequest = $RawGraphRequest | Where-Object -Property '@odata.context' -EQ $null | ConvertTo-FlatObject - $StatusCode = [HttpStatusCode]::OK - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - $StatusCode = [HttpStatusCode]::Forbidden - $GraphRequest = $ErrorMessage + } + } + } + $TenantFilter = $Request.Query.TenantFilter + try { + if ($TenantFilter -ne 'AllTenants') { + $RawGraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/$($Request.Query.Endpoint)" -tenantid $TenantFilter -NoPagination [boolean]$Request.query.DisablePagination -ComplexFilter + } else { + $RawGraphRequest = Get-Tenants | ForEach-Object -Parallel { + Import-Module '.\Modules\AzBobbyTables' + Import-Module '.\Modules\CIPPCore' + try { + $DefaultDomainName = $_.defaultDomainName + $TenantName = $_.displayName + New-GraphGetRequest -uri "https://graph.microsoft.com/beta/$($using:Request.Query.Endpoint)" -tenantid $DefaultDomainName -NoPagination [boolean]$using:Request.query.DisablePagination -ComplexFilter | Select-Object @{ + label = 'Tenant' + expression = { $TenantName } + }, * + } catch { + continue + } + } + } + $GraphRequest = $RawGraphRequest | Where-Object -Property '@odata.context' -EQ $null | ConvertTo-FlatObject + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + $StatusCode = [HttpStatusCode]::Forbidden + $GraphRequest = $ErrorMessage + } - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $StatusCode - Body = @($GraphRequest) - }) + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @($GraphRequest) + }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecPartnerWebhook.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecPartnerWebhook.ps1 index 045ad540318f..1e548d669016 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecPartnerWebhook.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecPartnerWebhook.ps1 @@ -7,6 +7,10 @@ function Invoke-ExecPartnerWebhook { #> Param($Request, $TriggerMetadata) + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + switch ($Request.Query.Action) { 'ListEventTypes' { $Uri = 'https://api.partnercenter.microsoft.com/webhooks/v1/registration/events' @@ -42,7 +46,7 @@ function Invoke-ExecPartnerWebhook { PartnerCenter = $true BaseURL = $BaseURL EventType = $Request.Body.EventType - Headers = $Request.Headers.'x-ms-client-principal' + Headers = $Request.Headers.'x-ms-client-principal' } $Results = New-CIPPGraphSubscription @Webhook diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecServicePrincipals.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecServicePrincipals.ps1 index a2f10c527808..44964e3b490e 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecServicePrincipals.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecServicePrincipals.ps1 @@ -8,6 +8,10 @@ function Invoke-ExecServicePrincipals { [CmdletBinding()] param($Request, $TriggerMetadata) + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $TenantFilter = $env:TenantID $Success = $true diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecSetCIPPAutoBackup.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecSetCIPPAutoBackup.ps1 index 67fab612224f..eacfe5b53646 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecSetCIPPAutoBackup.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecSetCIPPAutoBackup.ps1 @@ -9,6 +9,11 @@ Function Invoke-ExecSetCIPPAutoBackup { #> [CmdletBinding()] param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $unixtime = [int64](([datetime]::UtcNow) - (Get-Date '1/1/1970')).TotalSeconds if ($Request.Body.Enabled -eq 'True') { $Table = Get-CIPPTable -TableName 'ScheduledTasks' diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetCippAlerts.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetCippAlerts.ps1 index f10665096d54..f28ac30e189c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetCippAlerts.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetCippAlerts.ps1 @@ -10,6 +10,10 @@ Function Invoke-GetCippAlerts { [CmdletBinding()] param($Request, $TriggerMetadata) + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $Alerts = [System.Collections.Generic.List[object]]::new() $Table = Get-CippTable -tablename CippAlerts $PartitionKey = Get-Date -UFormat '%Y%m%d' diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetVersion.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetVersion.ps1 index 2a81fc1203a8..706ba63531c9 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetVersion.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-GetVersion.ps1 @@ -11,7 +11,8 @@ Function Invoke-GetVersion { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' $CIPPVersion = $request.query.LocalVersion diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListApiTest.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListApiTest.ps1 index 63c63d1637ca..4f359e0bd952 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListApiTest.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListApiTest.ps1 @@ -8,6 +8,10 @@ function Invoke-ListApiTest { [CmdletBinding()] param($Request, $TriggerMetadata) + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListGraphBulkRequest.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListGraphBulkRequest.ps1 index 017d0b60a2ce..045d9e55d818 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListGraphBulkRequest.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListGraphBulkRequest.ps1 @@ -8,16 +8,24 @@ function Invoke-ListGraphBulkRequest { [CmdletBinding()] param($Request, $TriggerMetadata) + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + $TenantFilter = $Request.Body.tenantFilter + $AsApp = $Request.Body.asApp + $Requests = $Request.Body.requests + $GraphRequestParams = @{ - tenantid = $Request.Body.tenantFilter + tenantid = $TenantFilter Requests = @() } - if ($Request.Body.asapp) { - $GraphRequestParams.asapp = $Request.Body.asApp + if ($AsApp) { + $GraphRequestParams.asapp = $AsApp } - $BulkRequests = foreach ($GraphRequest in $Request.Body.requests) { + $BulkRequests = foreach ($GraphRequest in $Requests) { if ($GraphRequest.method -eq 'GET') { @{ id = $GraphRequest.id diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListGraphRequest.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListGraphRequest.ps1 index d50178e4f6ab..47d517ac3371 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListGraphRequest.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ListGraphRequest.ps1 @@ -10,9 +10,9 @@ function Invoke-ListGraphRequest { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - + $Headers = $Request.Headers $Message = 'Accessed this API | Endpoint: {0}' -f $Request.Query.Endpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message $Message -Sev 'Debug' + Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Debug' $CippLink = ([System.Uri]$TriggerMetadata.Headers.Referer).PathAndQuery diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/invoke-ListEmptyResults.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/invoke-ListEmptyResults.ps1 index a41cdddebb13..132eb0ed62b1 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/invoke-ListEmptyResults.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/invoke-ListEmptyResults.ps1 @@ -10,6 +10,9 @@ Function invoke-ListEmptyResults { [CmdletBinding()] param($Request, $TriggerMetadata) + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionMapping.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionMapping.ps1 index dbd93185d239..50bc77460089 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionMapping.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionMapping.ps1 @@ -11,40 +11,38 @@ Function Invoke-ExecExtensionMapping { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' $Table = Get-CIPPTable -TableName CippMapping if ($Request.Query.List) { switch ($Request.Query.List) { 'HaloPSA' { - $body = Get-HaloMapping -CIPPMapping $Table + $Result = Get-HaloMapping -CIPPMapping $Table } 'NinjaOne' { - $Body = Get-NinjaOneOrgMapping -CIPPMapping $Table + $Result = Get-NinjaOneOrgMapping -CIPPMapping $Table } 'NinjaOneFields' { - $Body = Get-NinjaOneFieldMapping -CIPPMapping $Table + $Result = Get-NinjaOneFieldMapping -CIPPMapping $Table } 'Hudu' { - $Body = Get-HuduMapping -CIPPMapping $Table + $Result = Get-HuduMapping -CIPPMapping $Table } 'HuduFields' { - $Body = Get-HuduFieldMapping -CIPPMapping $Table + $Result = Get-HuduFieldMapping -CIPPMapping $Table } 'Sherweb' { - $Body = Get-SherwebMapping -CIPPMapping $Table + $Result = Get-SherwebMapping -CIPPMapping $Table } 'HaloPSAFields' { $TicketTypes = Get-HaloTicketType - $Body = @{'TicketTypes' = $TicketTypes } + $Result = @{'TicketTypes' = $TicketTypes } } 'PWPushFields' { $Accounts = Get-PwPushAccount - $Body = @{ + $Result = @{ 'Accounts' = $Accounts } } @@ -55,32 +53,35 @@ Function Invoke-ExecExtensionMapping { if ($Request.Query.AddMapping) { switch ($Request.Query.AddMapping) { 'Sherweb' { - $Body = Set-SherwebMapping -CIPPMapping $Table -APIName $APIName -Request $Request + $Result = Set-SherwebMapping -CIPPMapping $Table -APIName $APIName -Request $Request } 'HaloPSA' { - $body = Set-HaloMapping -CIPPMapping $Table -APIName $APIName -Request $Request + $Result = Set-HaloMapping -CIPPMapping $Table -APIName $APIName -Request $Request } 'NinjaOne' { - $Body = Set-NinjaOneOrgMapping -CIPPMapping $Table -APIName $APIName -Request $Request + $Result = Set-NinjaOneOrgMapping -CIPPMapping $Table -APIName $APIName -Request $Request Register-CIPPExtensionScheduledTasks } 'NinjaOneFields' { - $Body = Set-NinjaOneFieldMapping -CIPPMapping $Table -APIName $APIName -Request $Request -TriggerMetadata $TriggerMetadata + $Result = Set-NinjaOneFieldMapping -CIPPMapping $Table -APIName $APIName -Request $Request -TriggerMetadata $TriggerMetadata Register-CIPPExtensionScheduledTasks } 'Hudu' { - $Body = Set-HuduMapping -CIPPMapping $Table -APIName $APIName -Request $Request + $Result = Set-HuduMapping -CIPPMapping $Table -APIName $APIName -Request $Request Register-CIPPExtensionScheduledTasks } 'HuduFields' { - $Body = Set-ExtensionFieldMapping -CIPPMapping $Table -APIName $APIName -Request $Request -Extension 'Hudu' + $Result = Set-ExtensionFieldMapping -CIPPMapping $Table -APIName $APIName -Request $Request -Extension 'Hudu' Register-CIPPExtensionScheduledTasks } } } + $StatusCode = [HttpStatusCode]::OK } catch { - Write-LogMessage -API $APINAME -headers $Request.Headers -message "mapping API failed. $($_.Exception.Message)" -Sev 'Error' - $body = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" } + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Mapping API failed. $($ErrorMessage.NormalizedError)" + Write-LogMessage -API $APIName -headers $Headers -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } try { @@ -98,20 +99,23 @@ Function Invoke-ExecExtensionMapping { #Write-Host ($InputObject | ConvertTo-Json) $InstanceId = Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Depth 5 -Compress) Write-Host "Started permissions orchestration with ID = '$InstanceId'" - $Body = [pscustomobject]@{'Results' = 'Automapping Request has been queued. Exact name matches will appear first and matches on device names and serials will take longer. Please check the CIPP Logbook and refresh the page once complete.' } + $Result = 'AutoMapping Request has been queued. Exact name matches will appear first and matches on device names and serials will take longer. Please check the CIPP Logbook and refresh the page once complete.' } } } + $StatusCode = [HttpStatusCode]::OK } catch { - Write-LogMessage -API $APINAME -headers $Request.Headers -message "mapping API failed. $($_.Exception.Message)" -Sev 'Error' - $body = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" } + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Mapping API failed. $($ErrorMessage.NormalizedError)" + Write-LogMessage -API $APIName -headers $Headers -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body + StatusCode = $StatusCode + Body = @{Results = $Result } }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionSync.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionSync.ps1 index 239976f082f5..71848a9ca755 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionSync.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionSync.ps1 @@ -11,7 +11,8 @@ Function Invoke-ExecExtensionSync { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' switch ($Request.Query.Extension) { 'Gradient' { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionTest.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionTest.ps1 index a0c36e11d199..2d7800dcfb58 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionTest.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionTest.ps1 @@ -11,12 +11,14 @@ Function Invoke-ExecExtensionTest { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $Table = Get-CIPPTable -TableName Extensionsconfig $Configuration = ((Get-CIPPAzDataTableEntity @Table).config | ConvertFrom-Json) # Interact with query parameters or the body of the request. try { - switch ($Request.query.extensionName) { + switch ($Request.Query.extensionName) { 'HaloPSA' { $token = Get-HaloToken -configuration $Configuration.HaloPSA if ($token) { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionsConfig.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionsConfig.ps1 index afba503c5d7c..4745a28e3d7c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionsConfig.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ExecExtensionsConfig.ps1 @@ -10,8 +10,12 @@ Function Invoke-ExecExtensionsConfig { [CmdletBinding()] param($Request, $TriggerMetadata) + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $Body = [PSCustomObject]$Request.Body - $results = try { + $Results = try { # Check if NinjaOne URL is set correctly and the instance has at least version 5.6 if ($Body.NinjaOne) { $AllowedNinjaHostnames = @( @@ -59,7 +63,7 @@ Function Invoke-ExecExtensionsConfig { $AddObject = @{ PartitionKey = 'InstanceProperties' RowKey = 'CIPPURL' - Value = [string]([System.Uri]$Request.Headers.'x-ms-original-url').Host + Value = [string]([System.Uri]$Headers.'x-ms-original-url').Host } Write-Information ($AddObject | ConvertTo-Json -Compress) $ConfigTable = Get-CIPPTable -tablename 'Config' @@ -72,12 +76,11 @@ Function Invoke-ExecExtensionsConfig { } - $body = [pscustomobject]@{'Results' = $Results } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK - Body = $body + Body = @{'Results' = $Results } }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ListExtensionSync.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ListExtensionSync.ps1 index 2ae14ac3a13c..57cad5bd283d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ListExtensionSync.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Extensions/Invoke-ListExtensionSync.ps1 @@ -52,6 +52,6 @@ Function Invoke-ListExtensionSync { Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK - Body = ConvertTo-Json -Depth 5 -InputObject @($AllTasksArrayList) + Body = (ConvertTo-Json -Depth 5 -InputObject @($AllTasksArrayList)) }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Setup/Invoke-ExecSAMSetup.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Setup/Invoke-ExecSAMSetup.ps1 index c5c431ef50d4..d9780b9cc2cc 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Setup/Invoke-ExecSAMSetup.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Setup/Invoke-ExecSAMSetup.ps1 @@ -31,7 +31,9 @@ Function Invoke-ExecSAMSetup { } $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + if ($env:AzureWebJobsStorage -eq 'UseDevelopmentStorage=true') { $DevSecretsTable = Get-CIPPTable -tablename 'DevSecrets' $Secret = Get-CIPPAzDataTableEntity @DevSecretsTable -Filter "PartitionKey eq 'Secret' and RowKey eq 'Secret'" diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-AddContact.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-AddContact.ps1 new file mode 100644 index 000000000000..aeb1cd33411b --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-AddContact.ps1 @@ -0,0 +1,53 @@ +using namespace System.Net + +Function Invoke-AddContact { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.Contact.ReadWrite + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + $ContactObject = $Request.Body + $TenantId = $ContactObject.tenantid + + try { + + $BodyToship = [pscustomobject] @{ + displayName = $ContactObject.displayName + name = $ContactObject.displayName + ExternalEmailAddress = $ContactObject.email + FirstName = $ContactObject.firstName + LastName = $ContactObject.lastName + + } + # Create the contact + $NewContact = New-ExoRequest -tenantid $TenantId -cmdlet 'New-MailContact' -cmdParams $BodyToship -UseSystemMailbox $true + $null = New-ExoRequest -tenantid $TenantId -cmdlet 'Set-MailContact' -cmdParams @{Identity = $NewContact.id; HiddenFromAddressListsEnabled = [boolean]$ContactObject.hidefromGAL } -UseSystemMailbox $true + + # Log the result + $Result = "Created contact $($ContactObject.displayName) with id $($NewContact.id)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message $Result -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK + + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed to create contact. $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError + + } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @{Results = $Result } + }) + +} 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 new file mode 100644 index 000000000000..797025084402 --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-AddSharedMailbox.ps1 @@ -0,0 +1,83 @@ +using namespace System.Net + +Function Invoke-AddSharedMailbox { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.Mailbox.ReadWrite + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -Headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + $Results = [System.Collections.ArrayList]@() + $MailboxObject = $Request.Body + $Tenant = $MailboxObject.tenantID + $Aliases = $MailboxObject.addedAliases -Split '\n' + + try { + + $Email = "$($MailboxObject.username)@$($MailboxObject.domain)" + $BodyToShip = [pscustomobject] @{ + displayName = $MailboxObject.displayName + name = $MailboxObject.username + primarySMTPAddress = $Email + Shared = $true + } + $AddSharedRequest = New-ExoRequest -tenantid $Tenant -cmdlet 'New-Mailbox' -cmdParams $BodyToShip + $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 + try { + $null = Set-CIPPSignInState -userid $AddSharedRequest.ExternalDirectoryObjectId -TenantFilter $Tenant -APIName $APIName -Headers $Headers -AccountEnabled $false + $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)" + Write-LogMessage -Headers $Headers -API $APIName -tenant $Tenant -message $Message -Sev 'Error' -LogData $ErrorMessage + $Body = $Results.Add($Message) + } + + # 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 } + } + $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-Mailbox' -cmdParams $AliasBodyToShip -UseSystemMailbox $true + $Message = "Added aliases to $Email : $($Aliases -join ',')" + Write-LogMessage -Headers $Headers -API $APIName -tenant $Tenant -message $Message -Sev 'Info' + $Body = $Results.Add($Message) + + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Message = "Failed to add aliases to $Email : $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Headers -API $APIName -tenant $Tenant -message $Message -Sev 'Error' -LogData $ErrorMessage + $Body = $Results.Add($Message) + } + } + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Message = "Failed to create shared mailbox. $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Headers -API $APIName -tenant $Tenant -message $Message -Sev 'Error' -LogData $ErrorMessage + $Body = $Results.Add($Message) + $StatusCode = [HttpStatusCode]::Forbidden + } + + + $Body = [pscustomobject] @{ Results = @($Results) } + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = $Body + }) + +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditContact.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-EditContact.ps1 similarity index 87% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditContact.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-EditContact.ps1 index f08ca3c40bdf..d46143ce376c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditContact.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-EditContact.ps1 @@ -11,13 +11,13 @@ Function Invoke-EditContact { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $TenantID = $Request.body.tenantID $Headers = $Request.Headers - Write-LogMessage -Headers $Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + Write-LogMessage -Headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $TenantID = $Request.Body.tenantID try { # Extract contact information from the request body - $contactInfo = $Request.body + $contactInfo = $Request.Body # Log the received contact object Write-Host "Received contact object: $($contactInfo | ConvertTo-Json)" @@ -43,21 +43,20 @@ Function Invoke-EditContact { $null = New-ExoRequest -tenantid $TenantID -cmdlet 'Set-Contact' -cmdParams $bodyForSetContact -UseSystemMailbox $true $null = New-ExoRequest -tenantid $TenantID -cmdlet 'Set-MailContact' -cmdParams @{Identity = $contactInfo.ContactID; HiddenFromAddressListsEnabled = [System.Convert]::ToBoolean($contactInfo.hidefromGAL) } -UseSystemMailbox $true $Results = "Successfully edited contact $($contactInfo.DisplayName)" - Write-LogMessage -Headers $Headers -API $APINAME -tenant $TenantID -message $Results -Sev Info + Write-LogMessage -Headers $Headers -API $APIName -tenant $TenantID -message $Results -Sev Info $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ $Results = "Failed to edit contact. $($ErrorMessage.NormalizedError)" - Write-LogMessage -Headers $Headers -API $APINAME -tenant $TenantID -message $Results -Sev Error -LogData $ErrorMessage + Write-LogMessage -Headers $Headers -API $APIName -tenant $TenantID -message $Results -Sev Error -LogData $ErrorMessage $StatusCode = [HttpStatusCode]::InternalServerError } - $Results = [pscustomobject]@{'Results' = "$Results" } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = $StatusCode - Body = $Results + Body = @{Results = $Results } }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConvertMailbox.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecConvertMailbox.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecConvertMailbox.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecConvertMailbox.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecCopyForSent.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecCopyForSent.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecCopyForSent.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecCopyForSent.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEditCalendarPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEditCalendarPermissions.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEditCalendarPermissions.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEditCalendarPermissions.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEditMailboxPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEditMailboxPermissions.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEditMailboxPermissions.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEditMailboxPermissions.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEmailForward.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEmailForward.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEmailForward.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEmailForward.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEnableArchive.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEnableArchive.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecEnableArchive.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEnableArchive.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDelete.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecGroupsDelete.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDelete.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecGroupsDelete.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDeliveryManagement.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecGroupsDeliveryManagement.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsDeliveryManagement.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecGroupsDeliveryManagement.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsHideFromGAL.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecGroupsHideFromGAL.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecGroupsHideFromGAL.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecGroupsHideFromGAL.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecHideFromGAL.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecHideFromGAL.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecHideFromGAL.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecHideFromGAL.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailboxMobileDevices.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecMailboxMobileDevices.ps1 similarity index 90% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailboxMobileDevices.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecMailboxMobileDevices.ps1 index 5d752378f18a..2d54ba0aff50 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailboxMobileDevices.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecMailboxMobileDevices.ps1 @@ -14,10 +14,6 @@ Function Invoke-ExecMailboxMobileDevices { Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - - # Interact with query parameters or the body of the request. Try { $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 -Headers $Request.Headers diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecRemoveMailboxRule.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecRemoveMailboxRule.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecRemoveMailboxRule.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecRemoveMailboxRule.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecSetMailboxLocale.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecSetMailboxLocale.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecSetMailboxLocale.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecSetMailboxLocale.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecSetMailboxQuota.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecSetMailboxQuota.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecSetMailboxQuota.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecSetMailboxQuota.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecSetOoO.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecSetOoO.ps1 similarity index 97% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecSetOoO.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecSetOoO.ps1 index 1b60c5f7b8c0..952506bdc815 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecSetOoO.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecSetOoO.ps1 @@ -3,7 +3,9 @@ using namespace System.Net Function Invoke-ExecSetOoO { <# .FUNCTIONALITY - Entrypoint + Entrypoint + .ROLE + Exchange.Mailbox.ReadWrite #> [CmdletBinding()] param($Request, $TriggerMetadata) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecStartManagedFolderAssistant.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecStartManagedFolderAssistant.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecStartManagedFolderAssistant.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListCalendarPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListCalendarPermissions.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListCalendarPermissions.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListCalendarPermissions.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListContacts.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListContacts.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListContacts.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListContacts.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxMobileDevices.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListMailboxMobileDevices.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxMobileDevices.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListMailboxMobileDevices.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxRules.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListMailboxRules.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxRules.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListMailboxRules.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMailboxes.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListMailboxes.ps1 similarity index 96% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMailboxes.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListMailboxes.ps1 index bcbc251c921b..deb836716d5d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMailboxes.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListMailboxes.ps1 @@ -13,10 +13,6 @@ Function Invoke-ListMailboxes { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - # Interact with query parameters or the body of the request. $TenantFilter = $Request.Query.TenantFilter try { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListOoO.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListOoO.ps1 similarity index 92% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListOoO.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListOoO.ps1 index 3fe5c9a4a15b..2a1842db4d5b 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListOoO.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListOoO.ps1 @@ -13,7 +13,7 @@ Function Invoke-ListOoO { $APIName = $Request.Params.CIPPEndpoint $Tenantfilter = $request.query.tenantFilter try { - $Body = Get-CIPPOutOfOffice -userid $Request.query.userid -tenantFilter $TenantFilter -APIName $APINAME -Headers $Request.Headers + $Body = Get-CIPPOutOfOffice -UserID $Request.query.userid -tenantFilter $TenantFilter -APIName $APINAME -Headers $Request.Headers } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message $Body = [pscustomobject]@{'Results' = "Failed. $ErrorMessage" } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxStatistics.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListSharedMailboxStatistics.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharedMailboxStatistics.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListSharedMailboxStatistics.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListmailboxPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListmailboxPermissions.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListmailboxPermissions.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListmailboxPermissions.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-RemoveContact.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-RemoveContact.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemoveContact.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-RemoveContact.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddContact.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddContact.ps1 deleted file mode 100644 index 454db172aab0..000000000000 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddContact.ps1 +++ /dev/null @@ -1,48 +0,0 @@ -using namespace System.Net - -Function Invoke-AddContact { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.Contact.ReadWrite - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - $contactobj = $Request.body - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - try { - - $BodyToship = [pscustomobject] @{ - 'displayName' = $contactobj.Displayname - 'name' = $contactobj.displayName - 'ExternalEmailAddress' = $contactobj.Email - FirstName = $contactObj.firstname - lastname = $contactobj.lastname - - } - $NewContact = New-ExoRequest -tenantid $Request.body.tenantid -cmdlet 'New-MailContact' -cmdparams $BodyToship -UseSystemMailbox $true - Write-Host ( $NewContact | ConvertTo-Json) - New-ExoRequest -tenantid $Request.body.tenantid -cmdlet 'Set-MailContact' -cmdparams @{identity = $NewContact.id; HiddenFromAddressListsEnabled = [boolean]$contactobj.hidefromGAL } -UseSystemMailbox $true - $body = [pscustomobject]@{'Results' = 'Successfully added a contact.' } - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($contactobj.tenantid) -message "Created contact $($contactobj.displayname) with id $($GraphRequest.id) for " -Sev 'Info' - - } catch { - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($contactobj.tenantid) -message "Contact creation API failed. $($_.Exception.Message)" -Sev 'Error' - $body = [pscustomobject]@{'Results' = "Failed to create contact. $($_.Exception.Message)" } - - } - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Body - }) - -} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddExConnector.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddExConnector.ps1 deleted file mode 100644 index b475be078c06..000000000000 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddExConnector.ps1 +++ /dev/null @@ -1,38 +0,0 @@ -using namespace System.Net - -Function Invoke-AddExConnector { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.Connector.ReadWrite - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - $ConnectorType = ($Request.body.PowerShellCommand | ConvertFrom-Json).cippConnectorType - $RequestParams = $Request.Body.PowerShellCommand | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty GUID, cippConnectorType, comments - - $Tenants = ($Request.body.selectedTenants).value - $Result = foreach ($Tenantfilter in $tenants) { - try { - $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet "New-$($ConnectorType)connector" -cmdParams $RequestParams - "Successfully created Connector for $Tenantfilter." - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $Tenantfilter -message "Created Connector for $($Tenantfilter)" -sev 'Info' - } catch { - "Could not create created Connector for $($Tenantfilter): $($_.Exception.message)" - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $Tenantfilter -message "Could not create created Connector for $($Tenantfilter): $($_.Exception.message)" -sev 'Error' - } - } - - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = @{Results = @($Result) } - }) - -} 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 deleted file mode 100644 index d79795c18fa0..000000000000 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSharedMailbox.ps1 +++ /dev/null @@ -1,83 +0,0 @@ -using namespace System.Net - -Function Invoke-AddSharedMailbox { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.Mailbox.ReadWrite - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - $User = $Request.Headers - - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - - $Results = [System.Collections.ArrayList]@() - $MailboxObject = $Request.body - $Tenant = $MailboxObject.tenantid - $Aliases = $MailboxObject.addedAliases -Split '\n' - - try { - - $Email = "$($MailboxObject.username)@$($MailboxObject.domain)" - $BodyToShip = [pscustomobject] @{ - 'displayName' = $MailboxObject.Displayname - 'name' = $MailboxObject.username - 'primarySMTPAddress' = $Email - Shared = $true - } - $AddSharedRequest = New-ExoRequest -tenantid $Tenant -cmdlet 'New-Mailbox' -cmdparams $BodyToShip - $Body = $Results.add("Successfully created shared mailbox: $Email.") - Write-LogMessage -Headers $User -API $APINAME -tenant $Tenant -message "Created shared mailbox $($MailboxObject.displayname) with email $Email" -Sev 'Info' - - # Block sign-in for the mailbox - try { - $null = Set-CIPPSignInState -userid $AddSharedRequest.ExternalDirectoryObjectId -TenantFilter $Tenant -APIName $APINAME -Headers $User -AccountEnabled $false - $Body = $Results.add("Blocked sign-in for shared mailbox $Email") - } catch { - $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -tenant $Tenant -message "Failed to block sign-in for shared mailbox $Email. Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage - $Body = $Results.add("Failed to block sign-in for shared mailbox $Email. Error: $($ErrorMessage.NormalizedError)") - } - - # 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 } - } - $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-Mailbox' -cmdparams $AliasBodyToShip -UseSystemMailbox $true - Write-LogMessage -Headers $User -API $APINAME -tenant $Tenant -message "Added aliases to $Email : $($Aliases -join ',')" -Sev 'Info' - $Body = $results.add("Added Aliases to $Email : $($Aliases -join ',')") - - } catch { - $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -tenant $Tenant -message "Failed to add aliases to $Email : $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage - $Body = $results.add("ERROR: Failed to add aliases to $Email : $($ErrorMessage.NormalizedError)") - } - } - $StatusCode = [HttpStatusCode]::OK - } catch { - $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -tenant $Tenant -message "Failed to create shared mailbox. Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage - $Body = $Results.add("Failed to create Shared Mailbox. $($ErrorMessage.NormalizedError)") - $StatusCode = [HttpStatusCode]::Forbidden - } - - - $Body = [pscustomobject] @{ 'Results' = @($results) } - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $StatusCode - Body = $Body - }) - -} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSpamFilterTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSpamFilterTemplate.ps1 deleted file mode 100644 index 46e692cd809e..000000000000 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSpamFilterTemplate.ps1 +++ /dev/null @@ -1,53 +0,0 @@ -using namespace System.Net - -Function Invoke-AddSpamFilterTemplate { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.Spamfilter.ReadWrite - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - Write-Host ($request | ConvertTo-Json -Compress) - - try { - $GUID = (New-Guid).GUID - $JSON = if ($request.body.PowerShellCommand) { - Write-Host 'PowerShellCommand' - $request.body.PowerShellCommand | ConvertFrom-Json - } - else { - ([pscustomobject]$Request.body | Select-Object name, AddXHeaderValue, AdminDisplayName, AllowedSenderDomains, AllowedSenders, BlockedSenderDomains, BlockedSenders, BulkQuarantineTag, BulkSpamAction, BulkThreshold, Confirm, DownloadLink, EnableEndUserSpamNotifications, EnableLanguageBlockList, EnableRegionBlockList, EndUserSpamNotificationCustomFromAddress, EndUserSpamNotificationCustomFromName, EndUserSpamNotificationCustomSubject, EndUserSpamNotificationFrequency, EndUserSpamNotificationLanguage, EndUserSpamNotificationLimit, HighConfidencePhishAction, HighConfidencePhishQuarantineTag, HighConfidenceSpamAction, HighConfidenceSpamQuarantineTag, IncreaseScoreWithBizOrInfoUrls, IncreaseScoreWithImageLinks, IncreaseScoreWithNumericIps, IncreaseScoreWithRedirectToOtherPort, InlineSafetyTipsEnabled, LanguageBlockList, MarkAsSpamBulkMail, MarkAsSpamEmbedTagsInHtml, MarkAsSpamEmptyMessages, MarkAsSpamFormTagsInHtml, MarkAsSpamFramesInHtml, MarkAsSpamFromAddressAuthFail, MarkAsSpamJavaScriptInHtml, MarkAsSpamNdrBackscatter, MarkAsSpamObjectTagsInHtml, MarkAsSpamSensitiveWordList, MarkAsSpamSpfRecordHardFail, MarkAsSpamWebBugsInHtml, ModifySubjectValue, PhishQuarantineTag, PhishSpamAction, PhishZapEnabled, QuarantineRetentionPeriod, RecommendedPolicyType, RedirectToRecipients, RegionBlockList, SpamAction, SpamQuarantineTag, SpamZapEnabled, TestModeAction, TestModeBccToRecipients ) | ForEach-Object { - $NonEmptyProperties = $_.psobject.Properties | Where-Object { $null -ne $_.Value } | Select-Object -ExpandProperty Name - $_ | Select-Object -Property $NonEmptyProperties - } - } - $JSON = ($JSON | Select-Object @{n = 'name'; e = { $_.name } }, @{n = 'comments'; e = { $_.comments } }, * | ConvertTo-Json -Depth 10) - $Table = Get-CippTable -tablename 'templates' - $Table.Force = $true - Add-CIPPAzDataTableEntity @Table -Entity @{ - JSON = "$json" - RowKey = "$GUID" - PartitionKey = 'SpamfilterTemplate' - } - Write-LogMessage -headers $Request.Headers -API $APINAME -message "Created Spam Filter Template $($Request.body.name) with GUID $GUID" -Sev 'Debug' - $body = [pscustomobject]@{'Results' = 'Successfully added template' } - - } - catch { - Write-LogMessage -headers $Request.Headers -API $APINAME -message "Failed to create Spam Filter Template: $($_.Exception.Message)" -Sev 'Error' - $body = [pscustomobject]@{'Results' = "Spamfilter Template Deployment failed: $($_.Exception.Message)" } - } - - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) - -} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListAntiPhishingFilters.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListAntiPhishingFilters.ps1 index d303554b1358..3325c114db4f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListAntiPhishingFilters.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListAntiPhishingFilters.ps1 @@ -9,7 +9,8 @@ function Invoke-ListAntiPhishingFilters { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $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. diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListGlobalAddressList.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListGlobalAddressList.ps1 index 9067a2df0ac7..2801bb8e3a1c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListGlobalAddressList.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListGlobalAddressList.ps1 @@ -12,7 +12,8 @@ Function Invoke-ListGlobalAddressList { $APIName = $Request.Params.CIPPEndpoint $Headers = $Request.Headers - Write-LogMessage -Headers $Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + Write-LogMessage -Headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $TenantFilter = $Request.Query.tenantFilter try { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMailboxCAS.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMailboxCAS.ps1 index c088305a95c1..7ba5b3ec7c47 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMailboxCAS.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMailboxCAS.ps1 @@ -11,12 +11,10 @@ Function Invoke-ListMailboxCAS { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - # Interact with query parameters or the body of the request. $TenantFilter = $Request.Query.TenantFilter try { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMalwareFilters.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMalwareFilters.ps1 index d067881265cf..98a4e77be2b9 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMalwareFilters.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMalwareFilters.ps1 @@ -9,10 +9,11 @@ function Invoke-ListMalwareFilters { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $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. - $TenantFilter = $Request.Query.TenantFilter + $TenantFilter = $Request.Query.tenantFilter $Policies = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-MalwareFilterPolicy' | Select-Object -Property * $Rules = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-MalwareFilterRule' | Select-Object -Property * diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeAttachmentsFilters.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeAttachmentsFilters.ps1 index cea8b9313937..6df0401229fc 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeAttachmentsFilters.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeAttachmentsFilters.ps1 @@ -9,7 +9,8 @@ function Invoke-ListSafeAttachmentsFilters { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $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. $TenantFilter = $Request.Query.TenantFilter diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeLinksFilters.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeLinksFilters.ps1 index 0c7ced24871a..c9e395c05de7 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeLinksFilters.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSafeLinksFilters.ps1 @@ -9,7 +9,8 @@ function Invoke-ListSafeLinksFilters { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $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. $TenantFilter = $Request.Query.TenantFilter diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSharedMailboxAccountEnabled.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSharedMailboxAccountEnabled.ps1 index 1740ad53cc8d..eaea73fa0129 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSharedMailboxAccountEnabled.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListSharedMailboxAccountEnabled.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListSharedMailboxAccountEnabled { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' $TenantFilter = $Request.Query.tenantFilter diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddRoomMailbox.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-AddRoomMailbox.ps1 similarity index 68% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddRoomMailbox.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-AddRoomMailbox.ps1 index 0951cd7a3c09..0b7f139a7832 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddRoomMailbox.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-AddRoomMailbox.ps1 @@ -9,12 +9,13 @@ Function Invoke-AddRoomMailbox { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - $Tenant = $Request.body.tenantid - $User = $Request.Headers + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + $Tenant = $Request.Body.tenantid $Results = [System.Collections.Generic.List[Object]]::new() - $MailboxObject = $Request.body + $MailboxObject = $Request.Body $AddRoomParams = [pscustomobject]@{ Name = $MailboxObject.username DisplayName = $MailboxObject.displayName @@ -25,24 +26,24 @@ Function Invoke-AddRoomMailbox { } # Interact with query parameters or the body of the request. try { - $AddRoomRequest = New-ExoRequest -tenantid $Tenant -cmdlet 'New-Mailbox' -cmdparams $AddRoomParams + $AddRoomRequest = New-ExoRequest -tenantid $Tenant -cmdlet 'New-Mailbox' -cmdParams $AddRoomParams $Results.Add("Successfully created room: $($MailboxObject.DisplayName).") - Write-LogMessage -Headers $User -API $APINAME -tenant $Tenant -message "Created room $($MailboxObject.DisplayName) with id $($AddRoomRequest.id)" -Sev 'Info' + Write-LogMessage -Headers $Headers -API $APINAME -tenant $Tenant -message "Created room $($MailboxObject.DisplayName) with id $($AddRoomRequest.id)" -Sev 'Info' # Block sign-in for the mailbox try { - $Request = Set-CIPPSignInState -userid $AddRoomRequest.ExternalDirectoryObjectId -TenantFilter $Tenant -APIName $APINAME -Headers $User -AccountEnabled $false - $Results.add("Blocked sign-in for Room mailbox; $($MailboxObject.userPrincipalName)") + $Request = Set-CIPPSignInState -userid $AddRoomRequest.ExternalDirectoryObjectId -TenantFilter $Tenant -APIName $APINAME -Headers $Headers -AccountEnabled $false + $Results.Add("Blocked sign-in for Room mailbox; $($MailboxObject.userPrincipalName)") } catch { $ErrorMessage = Get-CippException -Exception $_ - $Results.add("Failed to block sign-in for Room mailbox: $($MailboxObject.userPrincipalName). Error: $($ErrorMessage.NormalizedError)") + $Results.Add("Failed to block sign-in for Room mailbox: $($MailboxObject.userPrincipalName). Error: $($ErrorMessage.NormalizedError)") } $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -tenant $Tenant -message "Failed to create room: $($MailboxObject.DisplayName). Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage + Write-LogMessage -Headers $Headers -API $APIName -tenant $Tenant -message "Failed to create room: $($MailboxObject.DisplayName). Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage $Results.Add("Failed to create Room mailbox $($MailboxObject.userPrincipalName). $($ErrorMessage.NormalizedError)") - $StatusCode = [HttpStatusCode]::Forbidden + $StatusCode = [HttpStatusCode]::InternalServerError } $Body = [pscustomobject] @{ 'Results' = @($Results) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditRoomMailbox.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-EditRoomMailbox.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditRoomMailbox.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-EditRoomMailbox.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListRoomLists.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-ListRoomLists.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListRoomLists.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-ListRoomLists.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListRooms.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-ListRooms.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListRooms.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-ListRooms.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSpamFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-AddSpamFilter.ps1 similarity index 52% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSpamFilter.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-AddSpamFilter.ps1 index 88def6633399..10d902c7a9cb 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddSpamFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-AddSpamFilter.ps1 @@ -12,16 +12,17 @@ Function Invoke-AddSpamFilter { $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -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.selectedTenants).value - $Result = foreach ($Tenantfilter in $tenants) { + $Result = foreach ($TenantFilter in $tenants) { try { - $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet 'New-HostedContentFilterPolicy' -cmdParams $RequestParams - $Domains = (New-ExoRequest -tenantid $Tenantfilter -cmdlet 'Get-AcceptedDomain').name + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'New-HostedContentFilterPolicy' -cmdParams $RequestParams + $Domains = (New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-AcceptedDomain').name $ruleparams = @{ 'name' = "$($RequestParams.name)" 'hostedcontentfilterpolicy' = "$($RequestParams.name)" @@ -29,12 +30,13 @@ Function Invoke-AddSpamFilter { 'Enabled' = $true 'Priority' = $RequestPriority } - $GraphRequest = New-ExoRequest -tenantid $Tenantfilter -cmdlet 'New-HostedContentFilterRule' -cmdParams $ruleparams - "Successfully created spamfilter for $tenantfilter." - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $tenantfilter -message "Created spamfilter rule for $($tenantfilter)" -sev Info + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'New-HostedContentFilterRule' -cmdParams $ruleparams + "Successfully created spamfilter for $TenantFilter." + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message "Successfully created spamfilter for $TenantFilter." -sev Info } catch { - "Could not create create spamfilter rule for $($tenantfilter): $($_.Exception.message)" - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $tenantfilter -message "Could not create create spamfilter rule for $($tenantfilter): $($_.Exception.message)" -sev Error + $ErrorMessage = Get-CippException -Exception $_ + "Could not create spamfilter rule for $($TenantFilter): $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message "Could not create spamfilter rule for $($TenantFilter): $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage } } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-AddSpamFilterTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-AddSpamFilterTemplate.ps1 new file mode 100644 index 000000000000..721caee1e338 --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-AddSpamFilterTemplate.ps1 @@ -0,0 +1,53 @@ +using namespace System.Net + +Function Invoke-AddSpamFilterTemplate { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.Spamfilter.ReadWrite + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + try { + $GUID = (New-Guid).GUID + $JSON = if ($Request.Body.PowerShellCommand) { + Write-Host 'PowerShellCommand' + $Request.Body.PowerShellCommand | ConvertFrom-Json + } else { + ([pscustomobject]$Request.Body | Select-Object name, AddXHeaderValue, AdminDisplayName, AllowedSenderDomains, AllowedSenders, BlockedSenderDomains, BlockedSenders, BulkQuarantineTag, BulkSpamAction, BulkThreshold, Confirm, DownloadLink, EnableEndUserSpamNotifications, EnableLanguageBlockList, EnableRegionBlockList, EndUserSpamNotificationCustomFromAddress, EndUserSpamNotificationCustomFromName, EndUserSpamNotificationCustomSubject, EndUserSpamNotificationFrequency, EndUserSpamNotificationLanguage, EndUserSpamNotificationCustomFromAddress, HighConfidencePhishAction, HighConfidencePhishQuarantineTag, HighConfidenceSpamAction, HighConfidenceSpamQuarantineTag, IncreaseScoreWithBizOrInfoUrls, IncreaseScoreWithImageLinks, IncreaseScoreWithNumericIps, IncreaseScoreWithRedirectToOtherPort, InlineSafetyTipsEnabled, LanguageBlockList, MarkAsSpamBulkMail, MarkAsSpamEmbedTagsInHtml, MarkAsSpamEmptyMessages, MarkAsSpamFormTagsInHtml, MarkAsSpamFramesInHtml, MarkAsSpamFromAddressAuthFail, MarkAsSpamJavaScriptInHtml, MarkAsSpamNdrBackscatter, MarkAsSpamObjectTagsInHtml, MarkAsSpamSensitiveWordList, MarkAsSpamSpfRecordHardFail, MarkAsSpamWebBugsInHtml, ModifySubjectValue, PhishQuarantineTag, PhishSpamAction, PhishZapEnabled, QuarantineRetentionPeriod, RecommendedPolicyType, RedirectToRecipients, RegionBlockList, SpamAction, SpamQuarantineTag, SpamZapEnabled, TestModeAction, TestModeBccToRecipients ) | ForEach-Object { + $NonEmptyProperties = $_.PSObject.Properties | Where-Object { $null -ne $_.Value } | Select-Object -ExpandProperty Name + $_ | Select-Object -Property $NonEmptyProperties + } + } + $JSON = ($JSON | Select-Object @{n = 'name'; e = { $_.name } }, @{n = 'comments'; e = { $_.comments } }, * | ConvertTo-Json -Depth 10) + $Table = Get-CippTable -tablename 'templates' + $Table.Force = $true + Add-CIPPAzDataTableEntity @Table -Entity @{ + JSON = "$json" + RowKey = "$GUID" + PartitionKey = 'SpamfilterTemplate' + } + $Result = "Successfully created Spam Filter Template: $($Request.Body.name) with GUID $GUID" + Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Debug' + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed to create Spam Filter Template: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError + } + + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @{Results = $Result } + }) + +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddTenantAllowBlockList.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-AddTenantAllowBlockList.ps1 similarity index 64% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddTenantAllowBlockList.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-AddTenantAllowBlockList.ps1 index 9f19cacea091..d43b14b56a9a 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddTenantAllowBlockList.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-AddTenantAllowBlockList.ps1 @@ -11,12 +11,11 @@ Function Invoke-AddTenantAllowBlockList { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - $blocklistobj = $Request.body - if ($Request.body.tenantId -eq 'AllTenants') { $Tenants = (Get-Tenants).defaultDomainName } else { $Tenants = @($Request.body.tenantId) } - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + $BlockListObject = $Request.Body + if ($Request.Body.tenantId -eq 'AllTenants') { $Tenants = (Get-Tenants).defaultDomainName } else { $Tenants = @($Request.body.tenantId) } $Results = [System.Collections.Generic.List[string]]::new() foreach ($Tenant in $Tenants) { try { @@ -24,20 +23,20 @@ Function Invoke-AddTenantAllowBlockList { tenantid = $Tenant cmdlet = 'New-TenantAllowBlockListItems' cmdParams = @{ - Entries = [string[]]$blocklistobj.entries - ListType = [string]$blocklistobj.listType - Notes = [string]$blocklistobj.notes - $blocklistobj.listMethod = [bool]$true + Entries = [string[]]$BlockListObject.entries + ListType = [string]$BlockListObject.listType + Notes = [string]$BlockListObject.notes + $BlockListObject.listMethod = [bool]$true } } - if ($blocklistobj.NoExpiration -eq $true) { + if ($BlockListObject.NoExpiration -eq $true) { $ExoRequest.cmdParams.NoExpiration = $true } New-ExoRequest @ExoRequest - $results.add("Successfully added $($blocklistobj.Entries) as type $($blocklistobj.ListType) to the $($blocklistobj.listMethod) list for $tenant") + $results.add("Successfully added $($BlockListObject.Entries) as type $($BlockListObject.ListType) to the $($BlockListObject.listMethod) list for $tenant") Write-LogMessage -headers $Request.Headers -API $APIName -tenant $Tenant -message $result -Sev 'Info' } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditAntiPhishingFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-EditAntiPhishingFilter.ps1 similarity index 97% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditAntiPhishingFilter.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-EditAntiPhishingFilter.ps1 index 86f787e74d1a..002f78839f1b 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditAntiPhishingFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-EditAntiPhishingFilter.ps1 @@ -1,57 +1,57 @@ -function Invoke-EditAntiPhishingFilter { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.SpamFilter.Read - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - $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. - $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter - $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName - $State = $Request.Query.State ?? $Request.Body.State - - try { - $ExoRequestParam = @{ - tenantid = $TenantFilter - cmdParams = @{ - Identity = $RuleName - } - useSystemMailbox = $true - } - - switch ($State) { - 'Enable' { - $ExoRequestParam.Add('cmdlet', 'Enable-AntiPhishRule') - } - 'Disable' { - $ExoRequestParam.Add('cmdlet', 'Disable-AntiPhishRule') - } - Default { - throw 'Invalid state' - } - } - $null = New-ExoRequest @ExoRequestParam - - $Result = "Successfully set Anti-Phishing rule $RuleName to $State" - Write-LogMessage -headers $Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev Info - $StatusCode = [HttpStatusCode]::OK - } catch { - $ErrorMessage = Get-CippException -Exception $_ - $Result = "Failed setting Anti-Phishing rule $RuleName to $State. Error: $($ErrorMessage.NormalizedError)" - Write-LogMessage -headers $Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage - $StatusCode = [HttpStatusCode]::InternalServerError - } - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $StatusCode - Body = @{Results = $Result } - }) -} +function Invoke-EditAntiPhishingFilter { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.SpamFilter.Read + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $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. + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName + $State = $Request.Query.State ?? $Request.Body.State + + try { + $ExoRequestParam = @{ + tenantid = $TenantFilter + cmdParams = @{ + Identity = $RuleName + } + useSystemMailbox = $true + } + + switch ($State) { + 'Enable' { + $ExoRequestParam.Add('cmdlet', 'Enable-AntiPhishRule') + } + 'Disable' { + $ExoRequestParam.Add('cmdlet', 'Disable-AntiPhishRule') + } + Default { + throw 'Invalid state' + } + } + $null = New-ExoRequest @ExoRequestParam + + $Result = "Successfully set Anti-Phishing rule $RuleName to $State" + Write-LogMessage -headers $Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev Info + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed setting Anti-Phishing rule $RuleName to $State. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError + } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @{Results = $Result } + }) +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditMalwareFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-EditMalwareFilter.ps1 similarity index 97% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditMalwareFilter.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-EditMalwareFilter.ps1 index fb1943714bf4..bb599a80f6f3 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditMalwareFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-EditMalwareFilter.ps1 @@ -1,57 +1,57 @@ -function Invoke-EditMalwareFilter { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.SpamFilter.Read - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - $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. - $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter - $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName - $State = $Request.Query.State ?? $Request.Body.State - - try { - $ExoRequestParam = @{ - tenantid = $TenantFilter - cmdParams = @{ - Identity = $RuleName - } - useSystemMailbox = $true - } - - switch ($State) { - 'Enable' { - $ExoRequestParam.Add('cmdlet', 'Enable-MalwareFilterRule') - } - 'Disable' { - $ExoRequestParam.Add('cmdlet', 'Disable-MalwareFilterRule') - } - Default { - throw 'Invalid state' - } - } - $null = New-ExoRequest @ExoRequestParam - - $Result = "Successfully set Malware Filter rule $($RuleName) to $($State)" - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev Info - $StatusCode = [HttpStatusCode]::OK - } catch { - $ErrorMessage = Get-CippException -Exception $_ - $Result = "Failed setting Malware Filter rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage - $StatusCode = [HttpStatusCode]::InternalServerError - } - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $StatusCode - Body = @{Results = $Result } - }) -} +function Invoke-EditMalwareFilter { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.SpamFilter.Read + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $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. + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName + $State = $Request.Query.State ?? $Request.Body.State + + try { + $ExoRequestParam = @{ + tenantid = $TenantFilter + cmdParams = @{ + Identity = $RuleName + } + useSystemMailbox = $true + } + + switch ($State) { + 'Enable' { + $ExoRequestParam.Add('cmdlet', 'Enable-MalwareFilterRule') + } + 'Disable' { + $ExoRequestParam.Add('cmdlet', 'Disable-MalwareFilterRule') + } + Default { + throw 'Invalid state' + } + } + $null = New-ExoRequest @ExoRequestParam + + $Result = "Successfully set Malware Filter rule $($RuleName) to $($State)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev Info + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed setting Malware Filter rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError + } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @{Results = $Result } + }) +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeAttachmentsFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-EditSafeAttachmentsFilter.ps1 similarity index 97% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeAttachmentsFilter.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-EditSafeAttachmentsFilter.ps1 index a6eae5585946..1adb00b34010 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeAttachmentsFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-EditSafeAttachmentsFilter.ps1 @@ -1,57 +1,57 @@ -function Invoke-EditSafeAttachmentsFilter { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.SpamFilter.Read - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - $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. - $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter - $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName - $State = $Request.Query.State ?? $Request.Body.State - - try { - $ExoRequestParam = @{ - tenantid = $TenantFilter - cmdParams = @{ - Identity = $RuleName - } - useSystemMailbox = $true - } - - switch ($State) { - 'Enable' { - $ExoRequestParam.Add('cmdlet', 'Enable-SafeAttachmentRule') - } - 'Disable' { - $ExoRequestParam.Add('cmdlet', 'Disable-SafeAttachmentRule') - } - Default { - throw 'Invalid state' - } - } - $null = New-ExoRequest @ExoRequestParam - - $Result = "Successfully set SafeAttachment rule $($RuleName) to $($State)" - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Info' - $StatusCode = [HttpStatusCode]::OK - } catch { - $ErrorMessage = Get-CippException -Exception $_ - $Result = "Failed setting SafeAttachment rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage - $StatusCode = [HttpStatusCode]::InternalServerError - } - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $StatusCode - Body = @{Results = $Result } - }) -} +function Invoke-EditSafeAttachmentsFilter { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.SpamFilter.Read + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $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. + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName + $State = $Request.Query.State ?? $Request.Body.State + + try { + $ExoRequestParam = @{ + tenantid = $TenantFilter + cmdParams = @{ + Identity = $RuleName + } + useSystemMailbox = $true + } + + switch ($State) { + 'Enable' { + $ExoRequestParam.Add('cmdlet', 'Enable-SafeAttachmentRule') + } + 'Disable' { + $ExoRequestParam.Add('cmdlet', 'Disable-SafeAttachmentRule') + } + Default { + throw 'Invalid state' + } + } + $null = New-ExoRequest @ExoRequestParam + + $Result = "Successfully set SafeAttachment rule $($RuleName) to $($State)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed setting SafeAttachment rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError + } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @{Results = $Result } + }) +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeLinksFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-EditSafeLinksFilter.ps1 similarity index 97% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeLinksFilter.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-EditSafeLinksFilter.ps1 index 89141c9f413e..fd7b11144b48 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeLinksFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-EditSafeLinksFilter.ps1 @@ -1,57 +1,57 @@ -function Invoke-EditSafeLinksFilter { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.SpamFilter.Read - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - $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. - $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter - $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName - $State = $Request.Query.State ?? $Request.Body.State - - try { - $ExoRequestParam = @{ - tenantid = $TenantFilter - cmdParams = @{ - Identity = $RuleName - } - useSystemMailbox = $true - } - - switch ($State) { - 'Enable' { - $ExoRequestParam.Add('cmdlet', 'Enable-SafeLinksRule') - } - 'Disable' { - $ExoRequestParam.Add('cmdlet', 'Disable-SafeLinksRule') - } - Default { - throw 'Invalid state' - } - } - $null = New-ExoRequest @ExoRequestParam - - $Result = "Successfully set SafeLinks rule $($RuleName) to $($State)" - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev Info - $StatusCode = [HttpStatusCode]::OK - } catch { - $ErrorMessage = Get-CippException -Exception $_ - $Result = "Failed setting SafeLinks rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' - $StatusCode = [HttpStatusCode]::InternalServerError - } - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $StatusCode - Body = @{Results = $Result } - }) -} +function Invoke-EditSafeLinksFilter { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.SpamFilter.Read + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $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. + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName + $State = $Request.Query.State ?? $Request.Body.State + + try { + $ExoRequestParam = @{ + tenantid = $TenantFilter + cmdParams = @{ + Identity = $RuleName + } + useSystemMailbox = $true + } + + switch ($State) { + 'Enable' { + $ExoRequestParam.Add('cmdlet', 'Enable-SafeLinksRule') + } + 'Disable' { + $ExoRequestParam.Add('cmdlet', 'Disable-SafeLinksRule') + } + Default { + throw 'Invalid state' + } + } + $null = New-ExoRequest @ExoRequestParam + + $Result = "Successfully set SafeLinks rule $($RuleName) to $($State)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev Info + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed setting SafeLinks rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' + $StatusCode = [HttpStatusCode]::InternalServerError + } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @{Results = $Result } + }) +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSpamFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-EditSpamFilter.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSpamFilter.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-EditSpamFilter.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecQuarantineManagement.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ExecQuarantineManagement.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecQuarantineManagement.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ExecQuarantineManagement.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListConnectionFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListConnectionFilter.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListConnectionFilter.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListConnectionFilter.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListConnectionFilterTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListConnectionFilterTemplates.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListConnectionFilterTemplates.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListConnectionFilterTemplates.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMailQuarantine.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListMailQuarantine.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMailQuarantine.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListMailQuarantine.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMailQuarantineMessage.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListMailQuarantineMessage.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMailQuarantineMessage.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListMailQuarantineMessage.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListSpamFilterTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListSpamFilterTemplates.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListSpamFilterTemplates.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListSpamFilterTemplates.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListSpamfilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListSpamfilter.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListSpamfilter.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListSpamfilter.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-RemoveConnectionfilterTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-RemoveConnectionfilterTemplate.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemoveConnectionfilterTemplate.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-RemoveConnectionfilterTemplate.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-RemoveSpamfilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-RemoveSpamfilter.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemoveSpamfilter.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-RemoveSpamfilter.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-RemoveSpamfilterTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-RemoveSpamfilterTemplate.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemoveSpamfilterTemplate.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-RemoveSpamfilterTemplate.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailTest.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Tools/Invoke-ExecMailTest.ps1 similarity index 97% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailTest.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Tools/Invoke-ExecMailTest.ps1 index 52281c5e24d4..e537a7d6ebdc 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailTest.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Tools/Invoke-ExecMailTest.ps1 @@ -12,9 +12,6 @@ Function Invoke-ExecMailTest { $APIName = $Request.Params.CIPPEndpoint Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' - try { switch ($Request.Query.Action) { 'CheckConfig' { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailboxRestore.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Tools/Invoke-ExecMailboxRestore.ps1 similarity index 97% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailboxRestore.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Tools/Invoke-ExecMailboxRestore.ps1 index b80c2fc0c750..8e46b2d163bb 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ExecMailboxRestore.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Tools/Invoke-ExecMailboxRestore.ps1 @@ -8,7 +8,8 @@ function Invoke-ExecMailboxRestore { Param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' try { switch ($Request.Query.Action) { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListExoRequest.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Tools/Invoke-ListExoRequest.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListExoRequest.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Tools/Invoke-ListExoRequest.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxRestores.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Tools/Invoke-ListMailboxRestores.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListMailboxRestores.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Tools/Invoke-ListMailboxRestores.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMessageTrace.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Tools/Invoke-ListMessageTrace.ps1 similarity index 95% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMessageTrace.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Tools/Invoke-ListMessageTrace.ps1 index c2f51fd1d89e..13f1f68a5fde 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListMessageTrace.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Tools/Invoke-ListMessageTrace.ps1 @@ -10,6 +10,10 @@ Function Invoke-ListMessageTrace { [CmdletBinding()] param($Request, $TriggerMetadata) + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + try { $TenantFilter = $Request.Body.tenantFilter diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddConnectionFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-AddConnectionFilter.ps1 similarity index 91% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddConnectionFilter.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-AddConnectionFilter.ps1 index 366ddbc8132c..c5443c3f5010 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddConnectionFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-AddConnectionFilter.ps1 @@ -19,12 +19,12 @@ Function Invoke-AddConnectionFilter { ConvertFrom-Json | Select-Object -Property *, @{Name = 'identity'; Expression = { $_.name } } -ExcludeProperty GUID, comments, name - $Tenants = ($Request.body.selectedTenants).value + $Tenants = ($Request.Body.selectedTenants).value $Result = foreach ($TenantFilter in $Tenants) { try { $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Set-HostedConnectionFilterPolicy' -cmdParams $RequestParams "Successfully created Connection filter for $TenantFilter." - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message "Updated Connection filter rule for $($TenantFilter)" -sev Info + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message "Successfully created Connection filter for $TenantFilter." -sev Info } catch { $ErrorMessage = Get-CippException -Exception $_ "Failed to create Connection Filter rule for $($TenantFilter): $($ErrorMessage.NormalizedError)" diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddConnectionFilterTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-AddConnectionFilterTemplate.ps1 similarity index 65% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddConnectionFilterTemplate.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-AddConnectionFilterTemplate.ps1 index a6d509c168cf..3b4230d3dd70 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddConnectionFilterTemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-AddConnectionFilterTemplate.ps1 @@ -11,7 +11,9 @@ Function Invoke-AddConnectionFilterTemplate { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + Write-Host ($request | ConvertTo-Json -Compress) try { @@ -19,8 +21,7 @@ Function Invoke-AddConnectionFilterTemplate { $JSON = if ($request.body.PowerShellCommand) { Write-Host 'PowerShellCommand' $request.body.PowerShellCommand | ConvertFrom-Json - } - else { + } else { $GUID = (New-Guid).GUID ([pscustomobject]$Request.body | Select-Object Name, EnableSafeList, IPAllowList , IPBlockList ) | ForEach-Object { $NonEmptyProperties = $_.psobject.Properties | Where-Object { $null -ne $_.Value } | Select-Object -ExpandProperty Name @@ -35,20 +36,21 @@ Function Invoke-AddConnectionFilterTemplate { RowKey = "$GUID" PartitionKey = 'ConnectionfilterTemplate' } - Write-LogMessage -headers $Request.Headers -API $APINAME -message "Created Connection Filter Template $($Request.body.name) with GUID $GUID" -Sev 'Debug' - $body = [pscustomobject]@{'Results' = 'Successfully added template' } - - } - catch { - Write-LogMessage -headers $Request.Headers -API $APINAME -message "Failed to create Connection Filter Template: $($_.Exception.Message)" -Sev 'Error' - $body = [pscustomobject]@{'Results' = "ConnectionFilter Template Deployment failed: $($_.Exception.Message)" } + $Result = "Successfully created Connection Filter Template: $($Request.Body.name) with GUID $GUID" + Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Debug' + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed to create Connection Filter Template: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body + StatusCode = $StatusCode + Body = @{Results = $Result } }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-AddExConnector.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-AddExConnector.ps1 new file mode 100644 index 000000000000..4991eebd0a8a --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-AddExConnector.ps1 @@ -0,0 +1,40 @@ +using namespace System.Net + +Function Invoke-AddExConnector { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.Connector.ReadWrite + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + + $ConnectorType = ($Request.Body.PowerShellCommand | ConvertFrom-Json).cippConnectorType + $RequestParams = $Request.Body.PowerShellCommand | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty GUID, cippConnectorType, comments + + $Tenants = ($Request.Body.selectedTenants).value + $Result = foreach ($TenantFilter in $Tenants) { + try { + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet "New-$($ConnectorType)connector" -cmdParams $RequestParams + "Successfully created Connector for $TenantFilter." + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message "Successfully created Connector for $TenantFilter." -sev 'Info' + } catch { + $ErrorMessage = Get-CippException -Exception $_ + "Could not create Connector for $($TenantFilter): $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message "Could not create Connector for $($TenantFilter): $($ErrorMessage.NormalizedError)" -sev 'Error' + } + } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = @{Results = @($Result) } + }) + +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddExConnectorTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-AddExConnectorTemplate.ps1 similarity index 63% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddExConnectorTemplate.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-AddExConnectorTemplate.ps1 index a91f35176339..f8580410ed3a 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddExConnectorTemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-AddExConnectorTemplate.ps1 @@ -11,24 +11,24 @@ Function Invoke-AddExConnectorTemplate { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - Write-Host ($request | ConvertTo-Json -Compress) + Write-Host ($Request | ConvertTo-Json -Compress) try { $GUID = (New-Guid).GUID - $Select = if ($Request.body.cippconnectortype -eq 'outbound') { + $Select = if ($Request.Body.cippconnectortype -eq 'outbound') { @( 'name', 'AllAcceptedDomains', 'CloudServicesMailEnabled', 'Comment', 'Confirm', 'ConnectorSource', 'ConnectorType', 'Enabled', 'IsTransportRuleScoped', 'RecipientDomains', 'RouteAllMessagesViaOnPremises', 'SenderRewritingEnabled', 'SmartHosts', 'TestMode', 'TlsDomain', 'TlsSettings', 'UseMXRecord' ) - } - else { + } else { @( 'name', 'SenderDomains', 'ConnectorSource', 'ConnectorType', 'EFSkipIPs', 'EFSkipLastIP', 'EFSkipMailGateway', 'EFTestMode', 'EFUsers', 'Enabled ', 'RequireTls', 'RestrictDomainsToCertificate', 'RestrictDomainsToIPAddresses', 'ScanAndDropRecipients', 'SenderIPAddresses', 'TlsSenderCertificateName', 'TreatMessagesAsInternal', 'TrustedOrganizations' ) } - $JSON = ([pscustomobject]$Request.body | Select-Object $Select) | ForEach-Object { + $JSON = ([pscustomobject]$Request.Body | Select-Object $Select) | ForEach-Object { $NonEmptyProperties = $_.psobject.Properties | Where-Object { $null -ne $_.Value } | Select-Object -ExpandProperty Name $_ | Select-Object -Property $NonEmptyProperties } @@ -36,24 +36,26 @@ Function Invoke-AddExConnectorTemplate { $Table = Get-CippTable -tablename 'templates' $Table.Force = $true Add-CIPPAzDataTableEntity @Table -Entity @{ - JSON = "$json" + JSON = "$JSON" RowKey = "$GUID" - direction = $request.body.cippconnectortype + direction = $Request.Body.cippconnectortype PartitionKey = 'ExConnectorTemplate' } - Write-LogMessage -headers $Request.Headers -API $APINAME -message "Created Connector Template $($Request.body.name) with GUID $GUID" -Sev 'Debug' - $body = [pscustomobject]@{'Results' = 'Successfully added template' } - } - catch { - Write-LogMessage -headers $Request.Headers -API $APINAME -message "Failed to create Connector Template: $($_.Exception.Message)" -Sev 'Error' - $body = [pscustomobject]@{'Results' = "Connector Template creation failed: $($_.Exception.Message)" } + $Result = "Successfully created Connector Template: $($Request.Body.name) with GUID $GUID" + Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Debug' + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed to create Connector Template: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Error' + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body + StatusCode = $StatusCode + Body = @{Results = $Result } }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddTransportRule.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-AddTransportRule.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddTransportRule.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-AddTransportRule.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddTransportTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-AddTransportTemplate.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-AddTransportTemplate.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-AddTransportTemplate.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditExConnector.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-EditExConnector.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditExConnector.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-EditExConnector.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditTransportRule.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-EditTransportRule.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditTransportRule.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-EditTransportRule.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExConnectorTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-ListExConnectorTemplates.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListExConnectorTemplates.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-ListExConnectorTemplates.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListExchangeConnectors.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-ListExchangeConnectors.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListExchangeConnectors.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-ListExchangeConnectors.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListTransportRules.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-ListTransportRules.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListTransportRules.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-ListTransportRules.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListTransportRulesTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-ListTransportRulesTemplates.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-ListTransportRulesTemplates.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-ListTransportRulesTemplates.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-RemoveExConnector.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-RemoveExConnector.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemoveExConnector.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-RemoveExConnector.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-RemoveExConnectorTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-RemoveExConnectorTemplate.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemoveExConnectorTemplate.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-RemoveExConnectorTemplate.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-RemoveTransportRule.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-RemoveTransportRule.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemoveTransportRule.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-RemoveTransportRule.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-RemoveTransportRuleTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-RemoveTransportRuleTemplate.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemoveTransportRuleTemplate.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-RemoveTransportRuleTemplate.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDefenderState.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListDefenderState.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListDefenderState.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListDefenderState.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDefenderTVM.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListDefenderTVM.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListDefenderTVM.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListDefenderTVM.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntunePolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntunePolicy.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntunePolicy.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntunePolicy.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntuneTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntuneTemplates.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntuneTemplates.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntuneTemplates.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-RemoveIntuneTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-RemoveIntuneTemplate.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemoveIntuneTemplate.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-RemoveIntuneTemplate.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-RemovePolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-RemovePolicy.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemovePolicy.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-RemovePolicy.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGroupTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroupTemplates.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListGroupTemplates.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroupTemplates.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-RemoveGroupTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-RemoveGroupTemplate.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemoveGroupTemplate.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-RemoveGroupTemplate.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-CIPPOffboardingJob.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-CIPPOffboardingJob.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-RemoveUser.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-RemoveUser.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemoveUser.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-RemoveUser.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharepointQuota.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListSharepointQuota.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListSharepointQuota.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListSharepointQuota.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDomains.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListDomains.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListDomains.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListDomains.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-RemoveCAPolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-RemoveCAPolicy.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemoveCAPolicy.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-RemoveCAPolicy.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-RemoveCATemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-RemoveCATemplate.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemoveCATemplate.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-RemoveCATemplate.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListServiceHealth.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Reports/Invoke-ListServiceHealth.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListServiceHealth.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Reports/Invoke-ListServiceHealth.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-CIPPStandardsRun.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-CIPPStandardsRun.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-CIPPStandardsRun.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-CIPPStandardsRun.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListStandards.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListStandards.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Entrypoints/Invoke-ListStandards.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListStandards.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-RemoveBPATemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-RemoveBPATemplate.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemoveBPATemplate.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-RemoveBPATemplate.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-RemoveStandard.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-RemoveStandard.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemoveStandard.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-RemoveStandard.ps1 diff --git a/Modules/CIPPCore/Public/Invoke-RemoveStandardTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-RemoveStandardTemplate.ps1 similarity index 100% rename from Modules/CIPPCore/Public/Invoke-RemoveStandardTemplate.ps1 rename to Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-RemoveStandardTemplate.ps1 From 1e9a80c22e5f35c0fa2a1a6ba3ecc4012b28695c Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Sat, 1 Mar 2025 14:24:00 +0100 Subject: [PATCH 099/167] updated a blank return to a clean exit --- .../Webhooks/Push-AuditLogBundleProcessing.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogBundleProcessing.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogBundleProcessing.ps1 index 757180f3a0bd..20744662daa8 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogBundleProcessing.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogBundleProcessing.ps1 @@ -1,8 +1,8 @@ function Push-AuditLogBundleProcessing { Param($Item) - return # Disabled for now, as it's not used - + #return # Disabled for now, as it's not used + exit 0 try { $AuditBundleTable = Get-CippTable -tablename 'AuditLogBundles' $AuditLogBundle = Get-CIPPAzDataTableEntity @AuditBundleTable -Filter "PartitionKey eq '$($Item.TenantFilter)' and RowKey eq '$($Item.ContentId)'" From 8f04d5692e33d048d5f750dc4a6b812a2f6230f6 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Sat, 1 Mar 2025 19:47:51 +0100 Subject: [PATCH 100/167] massive audit log update: seperate download and processing into different jobs --- .../AuditLogs/Get-CippAuditLogSearches.ps1 | 1 - .../New-CIPPAuditLogSearchResultsCache.ps1 | 70 +++++++++++++++++++ ...nt.ps1 => Push-AuditLogTenantDownload.ps1} | 44 +++--------- .../Webhooks/Push-AuditLogTenantProcess.ps1 | 29 ++++++++ .../Start-AuditLogOrchestrator.ps1 | 41 +++++++++-- .../Webhooks/Test-CIPPAuditLogRules.ps1 | 59 +++++++++++++--- 6 files changed, 194 insertions(+), 50 deletions(-) create mode 100644 Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 rename Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/{Push-AuditLogTenant.ps1 => Push-AuditLogTenantDownload.ps1} (63%) create mode 100644 Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenantProcess.ps1 diff --git a/Modules/CIPPCore/Public/AuditLogs/Get-CippAuditLogSearches.ps1 b/Modules/CIPPCore/Public/AuditLogs/Get-CippAuditLogSearches.ps1 index 1aac0b36eeab..693011c25aba 100644 --- a/Modules/CIPPCore/Public/AuditLogs/Get-CippAuditLogSearches.ps1 +++ b/Modules/CIPPCore/Public/AuditLogs/Get-CippAuditLogSearches.ps1 @@ -31,7 +31,6 @@ function Get-CippAuditLogSearches { return @() } $Queries = New-GraphBulkRequest -Requests @($BulkRequests) -AsApp $true -TenantId $TenantFilter | Select-Object -ExpandProperty body - $Queries = $Queries | Where-Object { $PendingQueries.RowKey -contains $_.id -and $_.status -eq 'succeeded' } } else { $Queries = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/security/auditLog/queries' -AsApp $true -tenantid $TenantFilter diff --git a/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 b/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 new file mode 100644 index 000000000000..9a16976f5204 --- /dev/null +++ b/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 @@ -0,0 +1,70 @@ +function New-CIPPAuditLogSearchResultsCache { + <# + .SYNOPSIS + Cache audit log search results for more efficient processing + .DESCRIPTION + Retrieves audit log searches for a tenant, processes them, and stores the results in a cache table. + Also tracks performance metrics for download and processing times. + .PARAMETER TenantFilter + The tenant to filter on. + #> + param ( + [Parameter(Mandatory = $true)] + [string]$TenantFilter, + [string]$SearchId + ) + + try { + Write-Information "Starting audit log cache process for tenant: $TenantFilter" + $CacheWebhooksTable = Get-CippTable -TableName 'CacheWebhooks' + $CacheWebhookStatsTable = Get-CippTable -TableName 'CacheWebhookStats' + # Start tracking download time + $downloadStartTime = Get-Date + # Process each search and store results in cache + try { + Write-Information "Processing search ID: $($SearchId) for tenant: $TenantFilter" + # Get the search results + #check if we haven't already downloaded this search by checking the cache table, if there are items with the same search id and tenant, we skip this search + $searchEntity = Get-CIPPAzDataTableEntity @CacheWebhooksTable -Filter "PartitionKey eq '$TenantFilter' and SearchId eq '$SearchId'" + if ($searchEntity) { + Write-Information "Search ID: $SearchId already cached for tenant: $TenantFilter" + exit 0 + } + $searchResults = Get-CippAuditLogSearchResults -TenantFilter $TenantFilter -QueryId $SearchId + # Store the results in the cache table + foreach ($searchResult in $searchResults) { + $cacheEntity = @{ + RowKey = $searchResult.id + PartitionKey = $TenantFilter + SearchId = $SearchId + JSON = [string]($searchResult | ConvertTo-Json -Depth 10) + } + Add-CIPPAzDataTableEntity @CacheWebhooksTable -Entity $cacheEntity -Force + } + Write-Information "Successfully cached search ID: $($item.id) for tenant: $TenantFilter" + } catch { + throw $_ + } + + # Calculate download time + $downloadEndTime = Get-Date + $downloadSeconds = ($downloadEndTime - $downloadStartTime).TotalSeconds + + # Store performance metrics + $statsEntity = @{ + RowKey = $TenantFilter + PartitionKey = 'Stats' + DownloadSecs = [string]$downloadSeconds + SearchCount = [string]$logSearches.Count + } + + Add-CIPPAzDataTableEntity @CacheWebhookStatsTable -Entity $statsEntity -Force + + Write-Information "Completed audit log cache process for tenant: $TenantFilter. Download time: $downloadSeconds seconds" + + return $logSearches.Count + } catch { + Write-Information "Error in New-CIPPAuditLogSearchResultsCache for tenant: $TenantFilter. Error: $($_.Exception.Message)" + throw $_ + } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenant.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenantDownload.ps1 similarity index 63% rename from Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenant.ps1 rename to Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenantDownload.ps1 index b55e4bc85dbf..51556092951f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenant.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenantDownload.ps1 @@ -1,10 +1,10 @@ -function Push-AuditLogTenant { +function Push-AuditLogTenantDownload { Param($Item) $ConfigTable = Get-CippTable -TableName 'WebhookRules' $TenantFilter = $Item.TenantFilter try { - Write-Information "Audit Logs: Processing $($TenantFilter)" + Write-Information "Audit Logs: Downloading $($TenantFilter)" # Get CIPP Url, cleanup legacy tasks $SchedulerConfig = Get-CippTable -TableName 'SchedulerConfig' $LegacyWebhookTasks = Get-CIPPAzDataTableEntity @SchedulerConfig -Filter "PartitionKey eq 'webhookcreation'" @@ -45,20 +45,15 @@ function Push-AuditLogTenant { if ($Configuration) { try { $LogSearches = Get-CippAuditLogSearches -TenantFilter $TenantFilter -ReadyToProcess | Select-Object -First 10 - Write-Information ('Audit Logs: Found {0} searches, begin processing' -f $LogSearches.Count) + Write-Information ('Audit Logs: Found {0} searches, begin downloading' -f $LogSearches.Count) foreach ($Search in $LogSearches) { $SearchEntity = Get-CIPPAzDataTableEntity @LogSearchesTable -Filter "Tenant eq '$($TenantFilter)' and RowKey eq '$($Search.id)'" $SearchEntity.CippStatus = 'Processing' Add-CIPPAzDataTableEntity @LogSearchesTable -Entity $SearchEntity -Force try { - # Test the audit log rules against the search results - $AuditLogTest = Test-CIPPAuditLogRules -TenantFilter $TenantFilter -SearchId $Search.id - - $SearchEntity.CippStatus = 'Completed' - $MatchedRules = [string](ConvertTo-Json -Compress -InputObject $AuditLogTest.MatchedRules) - $SearchEntity | Add-Member -MemberType NoteProperty -Name MatchedRules -Value $MatchedRules -Force - $SearchEntity | Add-Member -MemberType NoteProperty -Name MatchedLogs -Value $AuditLogTest.MatchedLogs -Force - $SearchEntity | Add-Member -MemberType NoteProperty -Name TotalLogs -Value $AuditLogTest.TotalLogs -Force + Write-Information "Audit Log search: Processing search ID: $($Search.id) for tenant: $TenantFilter" + $Downloads = New-CIPPAuditLogSearchResultsCache -TenantFilter $TenantFilter -searchId $Search.id + $SearchEntity.CippStatus = 'Downloaded' } catch { if ($_.Exception.Message -match 'Request rate is large. More Request Units may be needed, so no changes were made. Please retry this request later.') { $SearchEntity.CippStatus = 'Pending' @@ -74,34 +69,17 @@ function Push-AuditLogTenant { $SearchEntity.CippStatus = 'Failed' Write-Information "Error processing audit log rules: $($_.Exception.Message)" } - $AuditLogTest = [PSCustomObject]@{ - DataToProcess = @() - } + } Add-CIPPAzDataTableEntity @LogSearchesTable -Entity $SearchEntity -Force - $DataToProcess = ($AuditLogTest).DataToProcess - Write-Information "Audit Logs: Data to process found: $($DataToProcess.count) items" - if ($DataToProcess) { - foreach ($AuditLog in $DataToProcess) { - Write-Information "Processing $($AuditLog.operation)" - $Webhook = @{ - Data = $AuditLog - CIPPURL = [string]$CIPPURL - TenantFilter = $TenantFilter - } - try { - Invoke-CippWebhookProcessing @Webhook - } catch { - Write-Information "Error processing webhook: $($_.Exception.Message)" - } - } - } } } catch { - Write-Information ( 'Audit Log search: Error {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message) + Write-Information ('Audit Log search: Error {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message) + exit 0 } } } catch { - Write-Information ( 'Push-AuditLogTenant: Error {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message) + Write-Information ('Push-AuditLogTenant: Error {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message) + exit 0 } } diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenantProcess.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenantProcess.ps1 new file mode 100644 index 000000000000..8c3cd08297aa --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenantProcess.ps1 @@ -0,0 +1,29 @@ +function Push-AuditLogTenantProcess { + Param($Item) + $TenantFilter = $Item.TenantFilter + $RowIds = $Item.RowIds + + try { + Write-Information "Audit Logs: Processing $($TenantFilter) with $($RowIds.Count) row IDs. We're processing id $($RowIds[0]) to $($RowIds[-1])" + + # Get the CacheWebhooks table + $CacheWebhooksTable = Get-CippTable -TableName 'CacheWebhooks' + # we do it this way because the rows can grow extremely large, if we get them all it might just hang for minutes at a time. + $Rows = foreach ($RowId in $RowIds) { + $CacheEntity = Get-CIPPAzDataTableEntity @CacheWebhooksTable -Filter "PartitionKey eq '$TenantFilter' and RowKey eq '$RowId'" + if ($CacheEntity) { + $AuditData = $CacheEntity.JSON | ConvertFrom-Json -ErrorAction SilentlyContinue + $AuditData + } + } + + if ($Rows.Count -gt 0) { + Write-Information "Retrieved $($Rows.Count) rows from cache for processing" + Test-CIPPAuditLogRules -TenantFilter $TenantFilter -Rows $Rows + } else { + Write-Information 'No rows found in cache for the provided row IDs' + } + } catch { + Write-Information ('Push-AuditLogTenant: Error {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message) + } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 index 25deaf238213..9de12f33de69 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 @@ -19,17 +19,48 @@ function Start-AuditLogOrchestrator { } elseif (($WebhookRules | Measure-Object).Count -eq 0) { Write-Information 'No webhook rules defined' } else { - Write-Information "Audit Logs: Processing $($AuditLogSearches.Count) searches" + Write-Information "Audit Logs: Downloading $($AuditLogSearches.Count) searches" if ($PSCmdlet.ShouldProcess('Start-AuditLogOrchestrator', 'Starting Audit Log Polling')) { - $Queue = New-CippQueueEntry -Name 'Audit Log Collection' -Reference 'AuditLogCollection' -TotalTasks ($AuditLogSearches).Count - $Batch = $AuditLogSearches | Sort-Object -Property Tenant -Unique | Select-Object @{Name = 'TenantFilter'; Expression = { $_.Tenant } }, @{Name = 'QueueId'; Expression = { $Queue.RowKey } }, @{Name = 'FunctionName'; Expression = { 'AuditLogTenant' } } - + $Queue = New-CippQueueEntry -Name 'Audit Logs Download' -Reference 'AuditLogsDownload' -TotalTasks ($AuditLogSearches).Count + $Batch = $AuditLogSearches | Sort-Object -Property Tenant -Unique | Select-Object @{Name = 'TenantFilter'; Expression = { $_.Tenant } }, @{Name = 'QueueId'; Expression = { $Queue.RowKey } }, @{Name = 'FunctionName'; Expression = { 'AuditLogTenantDownload' } } $InputObject = [PSCustomObject]@{ - OrchestratorName = 'AuditLogs' + OrchestratorName = 'AuditLogsDownload' Batch = @($Batch) SkipLog = $true } Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Depth 5 -Compress) + Write-Information 'Starting audit log processing in batches of 1000, per tenant' + $WebhookCacheTable = Get-CippTable -TableName 'CacheWebhooks' + $WebhookCache = Get-CIPPAzDataTableEntity @WebhookCacheTable + $TenantGroups = $WebhookCache | Group-Object -Property PartitionKey + + if ($TenantGroups.Count -gt 0) { + Write-Information "Processing webhook cache for $($TenantGroups.Count) tenants" + $ProcessQueue = New-CippQueueEntry -Name 'Audit Logs Process' -Reference 'AuditLogsProcess' -TotalTasks ($TenantGroups | Measure-Object -Property Count -Sum).Sum + $ProcessBatch = foreach ($TenantGroup in $TenantGroups) { + $TenantFilter = $TenantGroup.Name + $RowIds = $TenantGroup.Group.RowKey + for ($i = 0; $i -lt $RowIds.Count; $i += 1000) { + $BatchRowIds = $RowIds[$i..([Math]::Min($i + 999, $RowIds.Count - 1))] + + [PSCustomObject]@{ + TenantFilter = $TenantFilter + RowIds = $BatchRowIds + QueueId = $ProcessQueue.RowKey + FunctionName = 'AuditLogTenantProcess' + } + } + } + if ($ProcessBatch.Count -gt 0) { + $ProcessInputObject = [PSCustomObject]@{ + OrchestratorName = 'AuditLogsProcess' + Batch = @($ProcessBatch) + SkipLog = $true + } + Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($ProcessInputObject | ConvertTo-Json -Depth 5 -Compress) + Write-Information "Started audit log processing orchestration with $($ProcessBatch.Count) batches" + } + } } } } catch { diff --git a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 index e820377bd909..664e9fd084c4 100644 --- a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 @@ -4,7 +4,7 @@ function Test-CIPPAuditLogRules { [Parameter(Mandatory = $true)] $TenantFilter, [Parameter(Mandatory = $true)] - $SearchId + $Rows ) $Results = [PSCustomObject]@{ @@ -14,6 +14,9 @@ function Test-CIPPAuditLogRules { DataToProcess = @() } + # Get the CacheWebhooks table for removing processed rows + $CacheWebhooksTable = Get-CippTable -TableName 'CacheWebhooks' + $ExtendedPropertiesIgnoreList = @( 'OAuth2:Authorize' 'OAuth2:Token' @@ -35,23 +38,24 @@ function Test-CIPPAuditLogRules { LogType = $_.Type } } - #write-warning 'Getting audit records from Graph API' + try { - $LogCount = Get-CippAuditLogSearchResults -TenantFilter $TenantFilter -QueryId $SearchId -CountOnly + $LogCount = $Rows.count $RunGuid = (New-Guid).Guid - Write-Warning "Logs to process: $LogCount - SearchId: $SearchId - RunGuid: $($RunGuid) - $($TenantFilter)" + Write-Warning "Logs to process: $LogCount - RunGuid: $($RunGuid) - $($TenantFilter)" $Results.TotalLogs = $LogCount - Write-Information "RunGuid: $RunGud - Collecting logs" - $SearchResults = Get-CippAuditLogSearchResults -TenantFilter $TenantFilter -QueryId $SearchId + Write-Information "RunGuid: $RunGuid - Collecting logs" + $SearchResults = $Rows } catch { Write-Warning "Error getting audit logs: $($_.Exception.Message)" - Write-LogMessage -API 'Webhooks' -message "Error getting audit logs for search $($SearchId)" -LogData (Get-CippException -Exception $_) -sev Error -tenant $TenantFilter + Write-LogMessage -API 'Webhooks' -message 'Error Processing Audit logs' -LogData (Get-CippException -Exception $_) -sev Error -tenant $TenantFilter throw $_ } if ($LogCount -gt 0) { $LocationTable = Get-CIPPTable -TableName 'knownlocationdb' $ProcessedData = foreach ($AuditRecord in $SearchResults) { + Write-Host "Auditlogs: The record is $($AuditRecord.operation) - $($TenantFilter)" $RootProperties = $AuditRecord | Select-Object * -ExcludeProperty auditData $Data = $AuditRecord.auditData | Select-Object *, CIPPAction, CIPPClause, CIPPGeoLocation, CIPPBadRepIP, CIPPHostedIP, CIPPIPDetected, CIPPLocationInfo, CIPPExtendedProperties, CIPPDeviceProperties, CIPPParameters, CIPPModifiedProperties, AuditRecord -ErrorAction SilentlyContinue try { @@ -179,10 +183,10 @@ function Test-CIPPAuditLogRules { $MatchedRules = [System.Collections.Generic.List[string]]::new() $DataToProcess = foreach ($clause in $Where) { - #write-warning "Webhook: Processing clause: $($clause.clause)" + Write-Warning "Webhook: Processing clause: $($clause.clause)" $ReturnedData = $ProcessedData | Where-Object { Invoke-Expression $clause.clause } if ($ReturnedData) { - #write-warning "Webhook: There is matching data: $(($ReturnedData.operation | Select-Object -Unique) -join ', ')" + Write-Warning "Webhook: There is matching data: $(($ReturnedData.operation | Select-Object -Unique) -join ', ')" $ReturnedData = foreach ($item in $ReturnedData) { $item.CIPPAction = $clause.expectedAction $item.CIPPClause = $clause.CIPPClause -join ' and ' @@ -196,6 +200,39 @@ function Test-CIPPAuditLogRules { $Results.MatchedLogs = ($DataToProcess | Measure-Object).Count $Results.DataToProcess = $DataToProcess } - Write-Warning "Finished - RunGuid: $($RunGuid) - $($TenantFilter)" - $Results + + if ($DataToProcess) { + $CippConfigTable = Get-CippTable -tablename Config + $CippConfig = Get-CIPPAzDataTableEntity @CippConfigTable -Filter "PartitionKey eq 'InstanceProperties' and RowKey eq 'CIPPURL'" + $CIPPURL = 'https://{0}' -f $CippConfig.Value + foreach ($AuditLog in $DataToProcess) { + Write-Information "Processing $($AuditLog.operation)" + $Webhook = @{ + Data = $AuditLog + CIPPURL = [string]$CIPPURL + TenantFilter = $TenantFilter + } + try { + Invoke-CippWebhookProcessing @Webhook + } catch { + Write-Information "Error sending final step of auditlog processing: $($_.Exception.Message)" + } + } + } + + # Remove processed rows from the cache table + try { + Write-Information 'Removing processed rows from cache' + foreach ($Row in $Rows) { + if ($Row.id) { + $RowEntity = Get-CIPPAzDataTableEntity @CacheWebhooksTable -Filter "PartitionKey eq '$TenantFilter' and RowKey eq '$($Row.id)'" + if ($RowEntity) { + Remove-AzDataTableEntity @CacheWebhooksTable -Entity $RowEntity -Force + Write-Information "Removed row $($Row.id) from cache" + } + } + } + } catch { + Write-Information "Error removing rows from cache: $($_.Exception.Message)" + } } From 80e31f18ab7f5f00e3fe1b8575c6ce9e6639926f Mon Sep 17 00:00:00 2001 From: John Duprey Date: Sun, 2 Mar 2025 10:30:06 -0500 Subject: [PATCH 101/167] fix: update logic for GDAP check role assignable --- Modules/CIPPCore/Public/Test-CIPPGDAPRelationships.ps1 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Test-CIPPGDAPRelationships.ps1 b/Modules/CIPPCore/Public/Test-CIPPGDAPRelationships.ps1 index 596fc6a8e19c..56a6074c91b0 100644 --- a/Modules/CIPPCore/Public/Test-CIPPGDAPRelationships.ps1 +++ b/Modules/CIPPCore/Public/Test-CIPPGDAPRelationships.ps1 @@ -57,12 +57,14 @@ function Test-CIPPGDAPRelationships { ) $RoleAssignableGroups = $SAMUserMemberships | Where-Object { $_.isAssignableToRole } $NestedGroups = foreach ($Group in $RoleAssignableGroups) { + Write-Information "Getting nested group memberships for $($Group.displayName)" New-GraphGetRequest -uri "https://graph.microsoft.com/beta/groups/$($Group.id)/memberOf?`$select=id,displayName" -NoAuthCheck $true } foreach ($Group in $ExpectedGroups) { $GroupFound = $false foreach ($Membership in ($SAMUserMemberships + $NestedGroups)) { - if ($Membership.displayName -match $Group -and (($CIPPGroupCount -gt 0 -and $Group -match 'M365 GDAP') -or $Group -notmatch 'M365 GDAP')) { + if ($Membership.displayName -match $Group) { + Write-Information "Found $Group in group memberships" $GroupFound = $true } } From 5ceda56393fd0d9395fad1b12c71ac0bf88eb895 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Sun, 2 Mar 2025 11:07:25 -0500 Subject: [PATCH 102/167] fix: tweak webhook exception message --- .../Activity Triggers/Push-SchedulerCIPPNotifications.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-SchedulerCIPPNotifications.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-SchedulerCIPPNotifications.ps1 index 08bbc50757f8..d465d57274cf 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-SchedulerCIPPNotifications.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-SchedulerCIPPNotifications.ps1 @@ -128,8 +128,8 @@ function Push-SchedulerCIPPNotifications { Add-CIPPAzDataTableEntity @Table -Entity $UpdateLogs -Force } } catch { - Write-Information "Could not send alerts to webhook: $($_.Exception.message)" - Write-LogMessage -API 'Alerts' -message "Could not send alerts to : $($_.Exception.message)" -tenant $Tenant -sev error + Write-Information "Could not send alerts to webhook $($config.webhook): $($_.Exception.message)" + Write-LogMessage -API 'Alerts' -message "Could not send alerts to webhook $($config.webhook): $($_.Exception.message)" -tenant $Tenant -sev error -LogData (Get-CippException -Exception $_) } if ($config.sendtoIntegration) { @@ -157,4 +157,4 @@ function Push-SchedulerCIPPNotifications { } -} \ No newline at end of file +} From 58d4eeeaffdfc889d2dfe78780f2960f7c81a3fb Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Sun, 2 Mar 2025 18:38:02 +0100 Subject: [PATCH 103/167] Add or update the Azure App Service build and deployment workflow config --- .github/workflows/dev_cippkwn4s-auditlog.yml | 30 ++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/dev_cippkwn4s-auditlog.yml diff --git a/.github/workflows/dev_cippkwn4s-auditlog.yml b/.github/workflows/dev_cippkwn4s-auditlog.yml new file mode 100644 index 000000000000..a6087052d3ad --- /dev/null +++ b/.github/workflows/dev_cippkwn4s-auditlog.yml @@ -0,0 +1,30 @@ +# 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 - cippkwn4s-auditlog + +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 + + steps: + - name: 'Checkout GitHub Action' + uses: actions/checkout@v4 + + - name: 'Run Azure Functions Action' + uses: Azure/functions-action@v1 + id: fa + with: + app-name: 'cippkwn4s-auditlog' + slot-name: 'Production' + package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }} + publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_34E06457AFD540C5ADCC893F70B5C245 }} \ No newline at end of file From d63f5cc5d50ee219f1af1c04fb89afb3e28e9c39 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Sun, 2 Mar 2025 18:39:03 +0100 Subject: [PATCH 104/167] Add or update the Azure App Service build and deployment workflow config --- .github/workflows/dev_cippkwn4s.yml | 30 +++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/dev_cippkwn4s.yml diff --git a/.github/workflows/dev_cippkwn4s.yml b/.github/workflows/dev_cippkwn4s.yml new file mode 100644 index 000000000000..904a72f5e546 --- /dev/null +++ b/.github/workflows/dev_cippkwn4s.yml @@ -0,0 +1,30 @@ +# 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 - cippkwn4s + +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 + + steps: + - name: 'Checkout GitHub Action' + uses: actions/checkout@v4 + + - name: 'Run Azure Functions Action' + uses: Azure/functions-action@v1 + id: fa + with: + app-name: 'cippkwn4s' + slot-name: 'Production' + package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }} + publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_D3DB920CED0443B791B30C72BBB395BE }} \ No newline at end of file From 42afc5e4785e59c053c5a83b19f6c60551022ced Mon Sep 17 00:00:00 2001 From: John Duprey Date: Sun, 2 Mar 2025 13:14:46 -0500 Subject: [PATCH 105/167] fix: pwpush exception handling --- .../Public/PwPush/New-PwPushLink.ps1 | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Modules/CippExtensions/Public/PwPush/New-PwPushLink.ps1 b/Modules/CippExtensions/Public/PwPush/New-PwPushLink.ps1 index a4afea1d7c17..5e9834f3beb8 100644 --- a/Modules/CippExtensions/Public/PwPush/New-PwPushLink.ps1 +++ b/Modules/CippExtensions/Public/PwPush/New-PwPushLink.ps1 @@ -6,15 +6,16 @@ function New-PwPushLink { $Table = Get-CIPPTable -TableName Extensionsconfig $Configuration = ((Get-CIPPAzDataTableEntity @Table).config | ConvertFrom-Json).PWPush if ($Configuration.Enabled -eq $true) { - Set-PwPushConfig -Configuration $Configuration - $PushParams = @{ - Payload = $Payload - } - if ($Configuration.ExpireAfterDays) { $PushParams.ExpireAfterDays = $Configuration.ExpireAfterDays } - if ($Configuration.ExpireAfterViews) { $PushParams.ExpireAfterViews = $Configuration.ExpireAfterViews } - if ($Configuration.DeletableByViewer) { $PushParams.DeletableByViewer = $Configuration.DeletableByViewer } - if ($Configuration.AccountId) { $PushParams.AccountId = $Configuration.AccountId.value } try { + Set-PwPushConfig -Configuration $Configuration + $PushParams = @{ + Payload = $Payload + } + if ($Configuration.ExpireAfterDays) { $PushParams.ExpireAfterDays = $Configuration.ExpireAfterDays } + if ($Configuration.ExpireAfterViews) { $PushParams.ExpireAfterViews = $Configuration.ExpireAfterViews } + if ($Configuration.DeletableByViewer) { $PushParams.DeletableByViewer = $Configuration.DeletableByViewer } + if ($Configuration.AccountId) { $PushParams.AccountId = $Configuration.AccountId.value } + if ($PSCmdlet.ShouldProcess('Create a new PwPush link')) { $Link = New-Push @PushParams if ($Configuration.RetrievalStep) { From cfa5e96338f838900d6c42e419172a516de4950e Mon Sep 17 00:00:00 2001 From: John Duprey Date: Sun, 2 Mar 2025 13:24:21 -0500 Subject: [PATCH 106/167] update passpushposh --- .../{1.3.1 => 1.3.2}/PSGetModuleInfo.xml | 56 ++++++++++--------- .../{1.3.1 => 1.3.2}/PassPushPosh.psd1 | 7 ++- .../{1.3.1 => 1.3.2}/PassPushPosh.psm1 | 18 ++++-- 3 files changed, 47 insertions(+), 34 deletions(-) rename Modules/PassPushPosh/{1.3.1 => 1.3.2}/PSGetModuleInfo.xml (71%) rename Modules/PassPushPosh/{1.3.1 => 1.3.2}/PassPushPosh.psd1 (95%) rename Modules/PassPushPosh/{1.3.1 => 1.3.2}/PassPushPosh.psm1 (98%) diff --git a/Modules/PassPushPosh/1.3.1/PSGetModuleInfo.xml b/Modules/PassPushPosh/1.3.2/PSGetModuleInfo.xml similarity index 71% rename from Modules/PassPushPosh/1.3.1/PSGetModuleInfo.xml rename to Modules/PassPushPosh/1.3.2/PSGetModuleInfo.xml index 0189606b3555..0621c3dcbeb3 100644 --- a/Modules/PassPushPosh/1.3.1/PSGetModuleInfo.xml +++ b/Modules/PassPushPosh/1.3.2/PSGetModuleInfo.xml @@ -7,13 +7,13 @@ PassPushPosh - 1.2.0 + 1.3.2 Module PassPushPosh is a PowerShell Module for accessing the Password Pusher application via API. It supports creating, retrieving, and deleting anonymous and authenticated pushes and getting Push and Dashboard data for authenticated users. Adam Burley AdamBurley Adam Burley, 2022 -
    2025-02-06T18:21:26-05:00
    +
    2025-03-01T20:45:35-05:00
    https://www.gnu.org/licenses/gpl-3.0.en.html @@ -41,12 +41,24 @@ - DscResource + Workflow + + RoleCapability + + + + DscResource + + + + Cmdlet + + Function @@ -55,6 +67,7 @@ Get-Dashboard Get-Push Get-PushAccount + Get-PushApiVersion Get-PushAuditLog Get-SecretLink Initialize-PassPushPosh @@ -63,14 +76,6 @@ - - RoleCapability - - - - Workflow - - Command @@ -79,6 +84,7 @@ Get-Dashboard Get-Push Get-PushAccount + Get-PushApiVersion Get-PushAuditLog Get-SecretLink Initialize-PassPushPosh @@ -87,14 +93,10 @@ - - Cmdlet - - - 1.2.0 - Add compatibility with Premium and Pro API endpoints and branding._x000D__x000A_ 1.0.0 - Major refactor, add capabilities and improve testing and build process._x000D__x000A_ 0.3.0 - Remove route translations from URI segments for compatibility with PasswordPusher v1.42.0. See pglombardo/PasswordPusher/pull/2353 + 1.3.2 - Bug fix for push JSON changes, add Version endpoint_x000D__x000A_ 1.2.0 - Add compatibility with Premium and Pro API endpoints and branding._x000D__x000A_ 1.0.0 - Major refactor, add capabilities and improve testing and build process._x000D__x000A_ 0.3.0 - Remove route translations from URI segments for compatibility with PasswordPusher v1.42.0. See pglombardo/PasswordPusher/pull/2353 @@ -111,19 +113,19 @@ Adam Burley, 2022 PassPushPosh is a PowerShell Module for accessing the Password Pusher application via API. It supports creating, retrieving, and deleting anonymous and authenticated pushes and getting Push and Dashboard data for authenticated users. False - 1.2.0 - Add compatibility with Premium and Pro API endpoints and branding._x000D__x000A_ 1.0.0 - Major refactor, add capabilities and improve testing and build process._x000D__x000A_ 0.3.0 - Remove route translations from URI segments for compatibility with PasswordPusher v1.42.0. See pglombardo/PasswordPusher/pull/2353 + 1.3.2 - Bug fix for push JSON changes, add Version endpoint_x000D__x000A_ 1.2.0 - Add compatibility with Premium and Pro API endpoints and branding._x000D__x000A_ 1.0.0 - Major refactor, add capabilities and improve testing and build process._x000D__x000A_ 0.3.0 - Remove route translations from URI segments for compatibility with PasswordPusher v1.42.0. See pglombardo/PasswordPusher/pull/2353 True True - 2 - 221 - 14279 - 2/6/2025 6:21:26 PM -05:00 - 2/6/2025 6:21:26 PM -05:00 - 2/6/2025 6:40:00 PM -05:00 - PSEdition_Core Windows Linux MacOS Password PSModule PSFunction_Get-Dashboard PSCommand_Get-Dashboard PSFunction_Get-Push PSCommand_Get-Push PSFunction_Get-PushAccount PSCommand_Get-PushAccount PSFunction_Get-PushAuditLog PSCommand_Get-PushAuditLog PSFunction_Get-SecretLink PSCommand_Get-SecretLink PSFunction_Initialize-PassPushPosh PSCommand_Initialize-PassPushPosh PSFunction_New-Push PSCommand_New-Push PSFunction_Remove-Push PSCommand_Remove-Push PSIncludes_Function + 4 + 247 + 16233 + 3/1/2025 8:45:35 PM -05:00 + 3/1/2025 8:45:35 PM -05:00 + 3/2/2025 9:40:00 AM -05:00 + PSEdition_Core Windows Linux MacOS Password PSModule PSFunction_Get-Dashboard PSCommand_Get-Dashboard PSFunction_Get-Push PSCommand_Get-Push PSFunction_Get-PushAccount PSCommand_Get-PushAccount PSFunction_Get-PushApiVersion PSCommand_Get-PushApiVersion PSFunction_Get-PushAuditLog PSCommand_Get-PushAuditLog PSFunction_Get-SecretLink PSCommand_Get-SecretLink PSFunction_Initialize-PassPushPosh PSCommand_Initialize-PassPushPosh PSFunction_New-Push PSCommand_New-Push PSFunction_Remove-Push PSCommand_Remove-Push PSIncludes_Function False - 2025-02-06T18:40:00Z - 1.2.0 + 2025-03-02T09:40:00Z + 1.3.2 Adam Burley false Module @@ -133,7 +135,7 @@ Burley.dev
    - C:\GitHub\CIPP Workspace\CIPP-API\Modules\PassPushPosh\1.2.0 + C:\GitHub\CIPP Workspace\CIPP-API\Modules\PassPushPosh\1.3.2 diff --git a/Modules/PassPushPosh/1.3.1/PassPushPosh.psd1 b/Modules/PassPushPosh/1.3.2/PassPushPosh.psd1 similarity index 95% rename from Modules/PassPushPosh/1.3.1/PassPushPosh.psd1 rename to Modules/PassPushPosh/1.3.2/PassPushPosh.psd1 index 3061f5864953..7243d064ae4e 100644 --- a/Modules/PassPushPosh/1.3.1/PassPushPosh.psd1 +++ b/Modules/PassPushPosh/1.3.2/PassPushPosh.psd1 @@ -3,7 +3,7 @@ # # Generated by: Adam Burley # -# Generated on: 2/21/2025 +# Generated on: 3/1/2025 # @{ @@ -12,7 +12,7 @@ RootModule = 'PassPushPosh.psm1' # Version number of this module. -ModuleVersion = '1.3.1' +ModuleVersion = '1.3.2' # Supported PSEditions CompatiblePSEditions = 'Core' @@ -69,7 +69,7 @@ PowerShellVersion = '7.0' # NestedModules = @() # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. -FunctionsToExport = @('Get-Dashboard','Get-Push','Get-PushAccount','Get-PushAuditLog','Get-SecretLink','Initialize-PassPushPosh','New-Push','Remove-Push') +FunctionsToExport = @('Get-Dashboard','Get-Push','Get-PushAccount','Get-PushApiVersion','Get-PushAuditLog','Get-SecretLink','Initialize-PassPushPosh','New-Push','Remove-Push') # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. CmdletsToExport = @() @@ -108,6 +108,7 @@ PrivateData = @{ # ReleaseNotes of this module ReleaseNotes = ' + 1.3.2 - Bug fix for push JSON changes, add Version endpoint 1.2.0 - Add compatibility with Premium and Pro API endpoints and branding. 1.0.0 - Major refactor, add capabilities and improve testing and build process. 0.3.0 - Remove route translations from URI segments for compatibility with PasswordPusher v1.42.0. See pglombardo/PasswordPusher/pull/2353' diff --git a/Modules/PassPushPosh/1.3.1/PassPushPosh.psm1 b/Modules/PassPushPosh/1.3.2/PassPushPosh.psm1 similarity index 98% rename from Modules/PassPushPosh/1.3.1/PassPushPosh.psm1 rename to Modules/PassPushPosh/1.3.2/PassPushPosh.psm1 index 35acb630d634..21e6657adb8b 100644 --- a/Modules/PassPushPosh/1.3.1/PassPushPosh.psm1 +++ b/Modules/PassPushPosh/1.3.2/PassPushPosh.psm1 @@ -278,7 +278,7 @@ function New-PasswordPusherUserAgent { Write-Debug "$userAtDomain transformed to $uAD64. First 20 characters $($uAD64.Substring(0,20))" # Version tag is replaced by the semantic version number at build time. See PassPushPosh/issues/11 for context - "PassPushPosh/1.3.1 $osVersion/$($uAD64.Substring(0,20))" + "PassPushPosh/1.3.2 $osVersion/$($uAD64.Substring(0,20))" } #EndRegion '.\Private\New-PasswordPusherUserAgent.ps1' 14 #Region '.\Public\Get-Dashboard.ps1' -1 @@ -457,6 +457,16 @@ function Get-PushAccount { } } #EndRegion '.\Public\Get-PushAccount.ps1' 22 +#Region '.\Public\Get-PushApiVersion.ps1' -1 + +function Get-PushApiVersion { + [CmdletBinding()] + [OutputType([PSCustomObject])] + param() + Initialize-PassPushPosh -Verbose:$VerbosePreference -Debug:$DebugPreference + Invoke-PasswordPusherAPI -Endpoint 'api/v1/version.json' +} +#EndRegion '.\Public\Get-PushApiVersion.ps1' 8 #Region '.\Public\Get-PushAuditLog.ps1' -1 <# @@ -736,9 +746,9 @@ function Initialize-PassPushPosh { } } 'Automatic' { - Write-Debug 'Legacy auth status not specified Checking for /up' - if ((Invoke-WebRequest "$_baseUrl/up" -SkipHttpErrorCheck).StatusCode -eq 200) { - Write-Debug "Current version detected via /up" + Write-Debug 'Legacy auth status not specified Checking for /version' + if ((Invoke-RestMethod "$_baseUrl/api/v1/version.json" -SkipHttpErrorCheck).Api_Version -gt 1.0) { + Write-Debug "Current version detected via /version" Set-Variable -Scope Script -Name PPPHeaders -WhatIf:$false -Value @{ 'Authorization' = "Bearer $_apiKey" } From f087279c67bf2468e1fda9857ef56691395fd6d7 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Sun, 2 Mar 2025 13:38:08 -0500 Subject: [PATCH 107/167] comment out type accelerator exception --- Modules/PassPushPosh/1.3.2/PassPushPosh.psm1 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Modules/PassPushPosh/1.3.2/PassPushPosh.psm1 b/Modules/PassPushPosh/1.3.2/PassPushPosh.psm1 index 21e6657adb8b..3f82a4a9ea18 100644 --- a/Modules/PassPushPosh/1.3.2/PassPushPosh.psm1 +++ b/Modules/PassPushPosh/1.3.2/PassPushPosh.psm1 @@ -60,7 +60,7 @@ class PasswordPush { $ExportableTypes =@( [PasswordPush] ) -# Get the internal TypeAccelerators class to use its static methods. +<## Get the internal TypeAccelerators class to use its static methods. $TypeAcceleratorsClass = [psobject].Assembly.GetType( 'System.Management.Automation.TypeAccelerators' ) @@ -81,10 +81,12 @@ foreach ($Type in $ExportableTypes) { $Type.FullName ) } -} +}#> # Add type accelerators for every exportable type. foreach ($Type in $ExportableTypes) { + try { $TypeAcceleratorsClass::Add($Type.FullName, $Type) + } catch {} } # Remove type accelerators when the module is removed. ($MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = { From 348d5979e982e3703692529fb76d0f63d849b317 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Sun, 2 Mar 2025 13:39:08 -0500 Subject: [PATCH 108/167] Update PassPushPosh.psm1 --- Modules/PassPushPosh/1.3.2/PassPushPosh.psm1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/PassPushPosh/1.3.2/PassPushPosh.psm1 b/Modules/PassPushPosh/1.3.2/PassPushPosh.psm1 index 3f82a4a9ea18..d1276e11e6cd 100644 --- a/Modules/PassPushPosh/1.3.2/PassPushPosh.psm1 +++ b/Modules/PassPushPosh/1.3.2/PassPushPosh.psm1 @@ -60,10 +60,11 @@ class PasswordPush { $ExportableTypes =@( [PasswordPush] ) -<## Get the internal TypeAccelerators class to use its static methods. +# Get the internal TypeAccelerators class to use its static methods. $TypeAcceleratorsClass = [psobject].Assembly.GetType( 'System.Management.Automation.TypeAccelerators' ) +<# # Ensure none of the types would clobber an existing type accelerator. # If a type accelerator with the same name exists, throw an exception. $ExistingTypeAccelerators = $TypeAcceleratorsClass::Get From 0524970022bf154c82459f25c8dacbd21607b677 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Sun, 2 Mar 2025 20:22:44 +0100 Subject: [PATCH 109/167] Testing rerun protection --- .../New-CIPPAuditLogSearchResultsCache.ps1 | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 b/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 index 9a16976f5204..48da780a68aa 100644 --- a/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 +++ b/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 @@ -14,6 +14,26 @@ function New-CIPPAuditLogSearchResultsCache { [string]$SearchId ) + # Rerun protection - Check if we already tried downloading this search ID in the last 4 hours + try { + $FailedDownloadsTable = Get-CippTable -TableName 'FailedAuditLogDownloads' + $fourHoursAgo = (Get-Date).AddHours(-4).ToUniversalTime() + + # Check if this search ID has a failed attempt in the last 4 hours + $failedEntity = Get-CIPPAzDataTableEntity @FailedDownloadsTable -Filter "PartitionKey eq '$TenantFilter' and SearchId eq '$SearchId' and Timestamp ge datetime'$($fourHoursAgo.ToString('yyyy-MM-ddTHH:mm:ssZ'))'" + + if ($failedEntity) { + $message = "Skipping search ID: $SearchId for tenant: $TenantFilter - Previous attempt failed within the last 4 hours" + Write-LogMessage -API "AuditLog" -tenant $TenantFilter -message $message -Sev "Info" + Write-Information $message + exit 0 + } + } + catch { + Write-Information "Error checking for failed downloads: $($_.Exception.Message)" + # Continue with the process even if the rerun protection check fails + } + try { Write-Information "Starting audit log cache process for tenant: $TenantFilter" $CacheWebhooksTable = Get-CippTable -TableName 'CacheWebhooks' @@ -43,6 +63,21 @@ function New-CIPPAuditLogSearchResultsCache { } Write-Information "Successfully cached search ID: $($item.id) for tenant: $TenantFilter" } catch { + # Record this failed attempt in the FailedAuditLogDownloads table + try { + $FailedDownloadsTable = Get-CippTable -TableName 'FailedAuditLogDownloads' + $failedEntity = @{ + RowKey = [guid]::NewGuid().ToString() + PartitionKey = $TenantFilter + SearchId = $SearchId + ErrorMessage = [string]$_.Exception.Message + } + Add-CIPPAzDataTableEntity @FailedDownloadsTable -Entity $failedEntity -Force + Write-Information "Recorded failed download for search ID: $SearchId, tenant: $TenantFilter" + } + catch { + Write-Information "Failed to record download failure: $($_.Exception.Message)" + } throw $_ } From f7b130ae1e3b8706290a2a9199a46530aa2e892b Mon Sep 17 00:00:00 2001 From: Esco Date: Sun, 2 Mar 2025 22:10:40 +0100 Subject: [PATCH 110/167] feat: Added permissions to low risk application consent --- .../Invoke-CIPPStandardOauthConsentLowSec.ps1 | 58 ++++++++++++++++--- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsentLowSec.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsentLowSec.ps1 index 9ab97150d1e3..da3d0063cdbb 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsentLowSec.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsentLowSec.ps1 @@ -31,26 +31,66 @@ function Invoke-CIPPStandardOauthConsentLowSec { ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'OauthConsentLowSec' $State = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' -tenantid $tenant) + $PermissionState = (New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/servicePrincipals(appId='00000003-0000-0000-c000-000000000000')/delegatedPermissionClassifications" -tenantid $tenant) | Select-Object -Property permissionName + + $requiredPermissions = @('offline_access', 'openid', 'User.Read', 'profile', 'email') + $missingPermissions = $requiredPermissions | Where-Object { $PermissionState.permissionName -notcontains $_ } + If ($Settings.remediate -eq $true) { - try { - if ($State.permissionGrantPolicyIdsAssignedToDefaultUserRole -notin @('managePermissionGrantsForSelf.microsoft-user-default-low')) { - Write-Host 'Going to set' - New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' -Type PATCH -Body '{"permissionGrantPolicyIdsAssignedToDefaultUserRole":["managePermissionGrantsForSelf.microsoft-user-default-low"]}' -ContentType 'application/json' + if ($State.permissionGrantPolicyIdsAssignedToDefaultUserRole -in @('managePermissionGrantsForSelf.microsoft-user-default-low')) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Application Consent Mode(microsoft-user-default-low) is already enabled.' -sev Info + } else { + try { + $GraphParam = @{ + tenantid = $tenant + Uri = 'https://graph.microsoft.com/beta/policies/authorizationPolicy/authorizationPolicy' + Type = 'PATCH' + Body = @{ + permissionGrantPolicyIdsAssignedToDefaultUserRole = @('managePermissionGrantsForSelf.microsoft-user-default-low') + } | ConvertTo-Json + ContentType = 'application/json' + } + $null = New-GraphPostRequest @GraphParam + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Application Consent Mode(microsoft-user-default-low) has been enabled.' -sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to apply Application Consent Mode (microsoft-user-default-low) Error: $ErrorMessage" -sev Error + } + } + + if ($missingPermissions.Count -eq 0) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'All permissions for Application Consent already assigned.' -sev Info + } else { + try { + $missingPermissions | ForEach-Object { + $GraphParam = @{ + tenantid = $tenant + Uri = "https://graph.microsoft.com/beta/servicePrincipals(appId='00000003-0000-0000-c000-000000000000')/delegatedPermissionClassifications" + Type = 'POST' + Body = @{ + permissionName = $_ + classification = 'low' + } | ConvertTo-Json + ContentType = 'application/json' + } + $null = New-GraphPostRequest @GraphParam + Write-LogMessage -API 'Standards' -tenant $tenant -message "Permission $_ has been added to low Application Consent" -sev Info + } + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to apply low consent permissions Error: $ErrorMessage" -sev Error } - Write-LogMessage -API 'Standards' -tenant $tenant -message 'Application Consent Mode(microsoft-user-default-low) has been enabled.' -sev Info - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to apply Application Consent Mode (microsoft-user-default-low) Error: $ErrorMessage" -sev Error } } - if ($Settings.alert -eq $true) { + if ($Settings.alert -eq $true) { if ($State.permissionGrantPolicyIdsAssignedToDefaultUserRole -notin @('managePermissionGrantsForSelf.microsoft-user-default-low')) { Write-LogMessage -API 'Standards' -tenant $tenant -message 'Application Consent Mode(microsoft-user-default-low) is not enabled.' -sev Alert } else { Write-LogMessage -API 'Standards' -tenant $tenant -message 'Application Consent Mode(microsoft-user-default-low) is enabled.' -sev Info } } + if ($Settings.report -eq $true) { if ($State.permissionGrantPolicyIdsAssignedToDefaultUserRole -notin @('managePermissionGrantsForSelf.microsoft-user-default-low')) { $State.permissionGrantPolicyIdsAssignedToDefaultUserRole = $false From 285268ea420b309cffe9656c3e4669d33b045756 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Sun, 2 Mar 2025 18:00:48 -0500 Subject: [PATCH 111/167] fix: better error handling with cipp sam admin roles --- Modules/CIPPCore/Public/Set-CIPPSAMAdminRoles.ps1 | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Modules/CIPPCore/Public/Set-CIPPSAMAdminRoles.ps1 b/Modules/CIPPCore/Public/Set-CIPPSAMAdminRoles.ps1 index 743b0a53c7d2..46eddbd432fd 100644 --- a/Modules/CIPPCore/Public/Set-CIPPSAMAdminRoles.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPSAMAdminRoles.ps1 @@ -20,10 +20,15 @@ function Set-CIPPSAMAdminRoles { $SAMRolesTable = Get-CIPPTable -tablename 'SAMRoles' $Roles = Get-CIPPAzDataTableEntity @SAMRolesTable - $SAMRoles = $Roles.Roles | ConvertFrom-Json - $Tenants = $Roles.Tenants | ConvertFrom-Json - if ($Tenants.value) { - $Tenants = $Tenants.value + try { + $SAMRoles = $Roles.Roles | ConvertFrom-Json -ErrorAction Stop + $Tenants = $Roles.Tenants | ConvertFrom-Json -ErrorAction Stop + if ($Tenants.value) { + $Tenants = $Tenants.value + } + } catch { + $ActionLogs.Add('CIPP-SAM roles not configured') + return $ActionLogs } if (($SAMRoles | Measure-Object).count -gt 0 -and $Tenants -contains $TenantFilter -or $Tenants -contains 'AllTenants') { From 35895bd8d89bf6224b694b8cafd7b6e254a59e8b Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 00:46:16 +0100 Subject: [PATCH 112/167] better rerun protection --- .../New-CIPPAuditLogSearchResultsCache.ps1 | 71 ++++++++++++------- 1 file changed, 47 insertions(+), 24 deletions(-) diff --git a/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 b/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 index 48da780a68aa..7e68dc6f582a 100644 --- a/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 +++ b/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 @@ -24,12 +24,11 @@ function New-CIPPAuditLogSearchResultsCache { if ($failedEntity) { $message = "Skipping search ID: $SearchId for tenant: $TenantFilter - Previous attempt failed within the last 4 hours" - Write-LogMessage -API "AuditLog" -tenant $TenantFilter -message $message -Sev "Info" + Write-LogMessage -API 'AuditLog' -tenant $TenantFilter -message $message -Sev 'Info' Write-Information $message exit 0 } - } - catch { + } catch { Write-Information "Error checking for failed downloads: $($_.Exception.Message)" # Continue with the process even if the rerun protection check fails } @@ -38,18 +37,39 @@ function New-CIPPAuditLogSearchResultsCache { Write-Information "Starting audit log cache process for tenant: $TenantFilter" $CacheWebhooksTable = Get-CippTable -TableName 'CacheWebhooks' $CacheWebhookStatsTable = Get-CippTable -TableName 'CacheWebhookStats' + + # Check if we haven't already downloaded this search by checking the cache table + $searchEntity = Get-CIPPAzDataTableEntity @CacheWebhooksTable -Filter "PartitionKey eq '$TenantFilter' and SearchId eq '$SearchId'" + if ($searchEntity) { + Write-Information "Search ID: $SearchId already cached for tenant: $TenantFilter" + exit 0 + } + + # Record this attempt in the FailedAuditLogDownloads table BEFORE starting the download + # This way, if the function is killed before completion, the record will remain + try { + $FailedDownloadsTable = Get-CippTable -TableName 'FailedAuditLogDownloads' + $attemptId = [guid]::NewGuid().ToString() + $failedEntity = @{ + RowKey = $attemptId + PartitionKey = $TenantFilter + SearchId = $SearchId + ErrorMessage = 'Download attempt in progress' + } + Add-CIPPAzDataTableEntity @FailedDownloadsTable -Entity $failedEntity -Force + Write-Information "Recorded download attempt for search ID: $SearchId, tenant: $TenantFilter" + } catch { + Write-Information "Failed to record download attempt: $($_.Exception.Message)" + # Continue with the process even if recording the attempt fails + } + # Start tracking download time $downloadStartTime = Get-Date + # Process each search and store results in cache try { Write-Information "Processing search ID: $($SearchId) for tenant: $TenantFilter" # Get the search results - #check if we haven't already downloaded this search by checking the cache table, if there are items with the same search id and tenant, we skip this search - $searchEntity = Get-CIPPAzDataTableEntity @CacheWebhooksTable -Filter "PartitionKey eq '$TenantFilter' and SearchId eq '$SearchId'" - if ($searchEntity) { - Write-Information "Search ID: $SearchId already cached for tenant: $TenantFilter" - exit 0 - } $searchResults = Get-CippAuditLogSearchResults -TenantFilter $TenantFilter -QueryId $SearchId # Store the results in the cache table foreach ($searchResult in $searchResults) { @@ -61,23 +81,26 @@ function New-CIPPAuditLogSearchResultsCache { } Add-CIPPAzDataTableEntity @CacheWebhooksTable -Entity $cacheEntity -Force } - Write-Information "Successfully cached search ID: $($item.id) for tenant: $TenantFilter" - } catch { - # Record this failed attempt in the FailedAuditLogDownloads table + Write-Information "Successfully cached search ID: $($SearchId) for tenant: $TenantFilter" + + # If we get here, the download was successful, so remove the failed download record try { $FailedDownloadsTable = Get-CippTable -TableName 'FailedAuditLogDownloads' - $failedEntity = @{ - RowKey = [guid]::NewGuid().ToString() - PartitionKey = $TenantFilter - SearchId = $SearchId - ErrorMessage = [string]$_.Exception.Message + # Get all records for this tenant and search ID + $failedEntities = Get-CIPPAzDataTableEntity @FailedDownloadsTable -Filter "PartitionKey eq '$TenantFilter' and SearchId eq '$SearchId'" + + # Remove each record + foreach ($entity in $failedEntities) { + Remove-CIPPAzDataTableEntity @FailedDownloadsTable -Entity $entity } - Add-CIPPAzDataTableEntity @FailedDownloadsTable -Entity $failedEntity -Force - Write-Information "Recorded failed download for search ID: $SearchId, tenant: $TenantFilter" - } - catch { - Write-Information "Failed to record download failure: $($_.Exception.Message)" + + if ($failedEntities) { + Write-Information "Removed failed download records for search ID: $SearchId, tenant: $TenantFilter" + } + } catch { + Write-Information "Failed to remove download attempt record: $($_.Exception.Message)" } + } catch { throw $_ } @@ -90,14 +113,14 @@ function New-CIPPAuditLogSearchResultsCache { RowKey = $TenantFilter PartitionKey = 'Stats' DownloadSecs = [string]$downloadSeconds - SearchCount = [string]$logSearches.Count + SearchCount = [string]($searchResults ? $searchResults.Count : 0) } Add-CIPPAzDataTableEntity @CacheWebhookStatsTable -Entity $statsEntity -Force Write-Information "Completed audit log cache process for tenant: $TenantFilter. Download time: $downloadSeconds seconds" - return $logSearches.Count + return ($searchResults ? $searchResults.Count : 0) } catch { Write-Information "Error in New-CIPPAuditLogSearchResultsCache for tenant: $TenantFilter. Error: $($_.Exception.Message)" throw $_ From b3174651c7dc4f91b2c1b131a30f844e86442ce3 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 00:49:49 +0100 Subject: [PATCH 113/167] rerun protection --- .../New-CIPPAuditLogSearchResultsCache.ps1 | 26 +------------------ 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 b/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 index 7e68dc6f582a..881ad4ba8503 100644 --- a/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 +++ b/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 @@ -13,13 +13,9 @@ function New-CIPPAuditLogSearchResultsCache { [string]$TenantFilter, [string]$SearchId ) - - # Rerun protection - Check if we already tried downloading this search ID in the last 4 hours try { $FailedDownloadsTable = Get-CippTable -TableName 'FailedAuditLogDownloads' $fourHoursAgo = (Get-Date).AddHours(-4).ToUniversalTime() - - # Check if this search ID has a failed attempt in the last 4 hours $failedEntity = Get-CIPPAzDataTableEntity @FailedDownloadsTable -Filter "PartitionKey eq '$TenantFilter' and SearchId eq '$SearchId' and Timestamp ge datetime'$($fourHoursAgo.ToString('yyyy-MM-ddTHH:mm:ssZ'))'" if ($failedEntity) { @@ -37,7 +33,6 @@ function New-CIPPAuditLogSearchResultsCache { Write-Information "Starting audit log cache process for tenant: $TenantFilter" $CacheWebhooksTable = Get-CippTable -TableName 'CacheWebhooks' $CacheWebhookStatsTable = Get-CippTable -TableName 'CacheWebhookStats' - # Check if we haven't already downloaded this search by checking the cache table $searchEntity = Get-CIPPAzDataTableEntity @CacheWebhooksTable -Filter "PartitionKey eq '$TenantFilter' and SearchId eq '$SearchId'" if ($searchEntity) { @@ -60,18 +55,12 @@ function New-CIPPAuditLogSearchResultsCache { Write-Information "Recorded download attempt for search ID: $SearchId, tenant: $TenantFilter" } catch { Write-Information "Failed to record download attempt: $($_.Exception.Message)" - # Continue with the process even if recording the attempt fails } - # Start tracking download time $downloadStartTime = Get-Date - - # Process each search and store results in cache try { Write-Information "Processing search ID: $($SearchId) for tenant: $TenantFilter" - # Get the search results $searchResults = Get-CippAuditLogSearchResults -TenantFilter $TenantFilter -QueryId $SearchId - # Store the results in the cache table foreach ($searchResult in $searchResults) { $cacheEntity = @{ RowKey = $searchResult.id @@ -82,19 +71,11 @@ function New-CIPPAuditLogSearchResultsCache { Add-CIPPAzDataTableEntity @CacheWebhooksTable -Entity $cacheEntity -Force } Write-Information "Successfully cached search ID: $($SearchId) for tenant: $TenantFilter" - - # If we get here, the download was successful, so remove the failed download record try { $FailedDownloadsTable = Get-CippTable -TableName 'FailedAuditLogDownloads' - # Get all records for this tenant and search ID $failedEntities = Get-CIPPAzDataTableEntity @FailedDownloadsTable -Filter "PartitionKey eq '$TenantFilter' and SearchId eq '$SearchId'" - - # Remove each record - foreach ($entity in $failedEntities) { - Remove-CIPPAzDataTableEntity @FailedDownloadsTable -Entity $entity - } - if ($failedEntities) { + Remove-CIPPAzDataTableEntity @FailedDownloadsTable -Entity $entity Write-Information "Removed failed download records for search ID: $SearchId, tenant: $TenantFilter" } } catch { @@ -104,22 +85,17 @@ function New-CIPPAuditLogSearchResultsCache { throw $_ } - # Calculate download time $downloadEndTime = Get-Date $downloadSeconds = ($downloadEndTime - $downloadStartTime).TotalSeconds - # Store performance metrics $statsEntity = @{ RowKey = $TenantFilter PartitionKey = 'Stats' DownloadSecs = [string]$downloadSeconds SearchCount = [string]($searchResults ? $searchResults.Count : 0) } - Add-CIPPAzDataTableEntity @CacheWebhookStatsTable -Entity $statsEntity -Force - Write-Information "Completed audit log cache process for tenant: $TenantFilter. Download time: $downloadSeconds seconds" - return ($searchResults ? $searchResults.Count : 0) } catch { Write-Information "Error in New-CIPPAuditLogSearchResultsCache for tenant: $TenantFilter. Error: $($_.Exception.Message)" From ab0d7da4ff9eb9a7c7778c929fbac44929fcda8f Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 01:30:23 +0100 Subject: [PATCH 114/167] logging fixes --- .../Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 | 3 +-- Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 b/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 index 881ad4ba8503..9faa4b07b0fc 100644 --- a/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 +++ b/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 @@ -26,7 +26,6 @@ function New-CIPPAuditLogSearchResultsCache { } } catch { Write-Information "Error checking for failed downloads: $($_.Exception.Message)" - # Continue with the process even if the rerun protection check fails } try { @@ -75,7 +74,7 @@ function New-CIPPAuditLogSearchResultsCache { $FailedDownloadsTable = Get-CippTable -TableName 'FailedAuditLogDownloads' $failedEntities = Get-CIPPAzDataTableEntity @FailedDownloadsTable -Filter "PartitionKey eq '$TenantFilter' and SearchId eq '$SearchId'" if ($failedEntities) { - Remove-CIPPAzDataTableEntity @FailedDownloadsTable -Entity $entity + Remove-AzDataTableEntity @FailedDownloadsTable -Entity $entity Write-Information "Removed failed download records for search ID: $SearchId, tenant: $TenantFilter" } } catch { diff --git a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 index 664e9fd084c4..5dac3d62d297 100644 --- a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 @@ -55,7 +55,7 @@ function Test-CIPPAuditLogRules { if ($LogCount -gt 0) { $LocationTable = Get-CIPPTable -TableName 'knownlocationdb' $ProcessedData = foreach ($AuditRecord in $SearchResults) { - Write-Host "Auditlogs: The record is $($AuditRecord.operation) - $($TenantFilter)" + #Write-Host "Auditlogs: The record is $($AuditRecord.operation) - $($TenantFilter)" $RootProperties = $AuditRecord | Select-Object * -ExcludeProperty auditData $Data = $AuditRecord.auditData | Select-Object *, CIPPAction, CIPPClause, CIPPGeoLocation, CIPPBadRepIP, CIPPHostedIP, CIPPIPDetected, CIPPLocationInfo, CIPPExtendedProperties, CIPPDeviceProperties, CIPPParameters, CIPPModifiedProperties, AuditRecord -ErrorAction SilentlyContinue try { From 426427c6d180734823536ff54905bf863f91a723 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 01:49:12 +0100 Subject: [PATCH 115/167] tablecleanup daily downloaded queries --- .../Public/Entrypoints/Timer Functions/Start-TableCleanup.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Timer Functions/Start-TableCleanup.ps1 b/Modules/CIPPCore/Public/Entrypoints/Timer Functions/Start-TableCleanup.ps1 index ff635480a672..21dcd6a7e9aa 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Timer Functions/Start-TableCleanup.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Timer Functions/Start-TableCleanup.ps1 @@ -17,7 +17,7 @@ function Start-TableCleanup { @{ DataTableProps = @{ Context = (Get-CIPPTable -tablename 'AuditLogSearches').Context - Filter = "Timestamp lt datetime'$((Get-Date).AddDays(-7).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ'))'" + Filter = "Timestamp lt datetime'$((Get-Date).AddDays(-1).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ'))'" First = 10000 Property = @('PartitionKey', 'RowKey', 'ETag') } From 11de9eff18044f311f1f9884f4a68b5e616b69e7 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Sun, 2 Mar 2025 21:10:23 -0500 Subject: [PATCH 116/167] fix: addtogroup functionality --- .../Identity/Administration/Users/Invoke-EditUser.ps1 | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) 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 aaf0fd5f0a15..31f09b0df2ae 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 @@ -140,15 +140,14 @@ Function Invoke-EditUser { if ($AddToGroups) { $AddToGroups | ForEach-Object { - $GroupType = $_.value.groupType -join ',' - $GroupID = $_.value.groupid - $GroupName = $_.value.groupName + $GroupType = $_.addedFields.calculatedGroupType + $GroupID = $_.value + $GroupName = $_.label Write-Host "About to add $($UserObj.userPrincipalName) to $GroupName. Group ID is: $GroupID and type is: $GroupType" try { if ($GroupType -eq 'Distribution list' -or $GroupType -eq 'Mail-Enabled Security') { - Write-Host 'Adding to group via Add-DistributionGroupMember ' $Params = @{ Identity = $GroupID; Member = $UserObj.id; BypassSecurityGroupManagerCheck = $true } $null = New-ExoRequest -tenantid $UserObj.tenantFilter -cmdlet 'Add-DistributionGroupMember' -cmdParams $params -UseSystemMailbox $true From 90b1bbbf7c09df4943fad57b6fbaae9567ba336c Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 11:43:43 +0100 Subject: [PATCH 117/167] correction for duplicate detection --- .../Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 b/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 index 9faa4b07b0fc..ea00d38cbe48 100644 --- a/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 +++ b/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 @@ -74,7 +74,7 @@ function New-CIPPAuditLogSearchResultsCache { $FailedDownloadsTable = Get-CippTable -TableName 'FailedAuditLogDownloads' $failedEntities = Get-CIPPAzDataTableEntity @FailedDownloadsTable -Filter "PartitionKey eq '$TenantFilter' and SearchId eq '$SearchId'" if ($failedEntities) { - Remove-AzDataTableEntity @FailedDownloadsTable -Entity $entity + Remove-AzDataTableEntity @FailedDownloadsTable -Entity $failedEntities Write-Information "Removed failed download records for search ID: $SearchId, tenant: $TenantFilter" } } catch { From 5943cb4b6caacf47ea075383f496bd8c977d5dd2 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 12:22:52 +0100 Subject: [PATCH 118/167] added orch logging for app insihgt --- Modules/CippEntrypoints/CippEntrypoints.psm1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/CippEntrypoints/CippEntrypoints.psm1 b/Modules/CippEntrypoints/CippEntrypoints.psm1 index 4378bc872d98..7c0a29c636fa 100644 --- a/Modules/CippEntrypoints/CippEntrypoints.psm1 +++ b/Modules/CippEntrypoints/CippEntrypoints.psm1 @@ -63,7 +63,7 @@ function Receive-CippHttpTrigger { function Receive-CippOrchestrationTrigger { param($Context) - + try { if (Test-Json -Json $Context.Input) { $OrchestratorInput = $Context.Input | ConvertFrom-Json @@ -71,7 +71,7 @@ function Receive-CippOrchestrationTrigger { $OrchestratorInput = $Context.Input } Write-Information "Orchestrator started $($OrchestratorInput.OrchestratorName)" - + Write-Warning "Receive-CippOrchestrationTrigger - $($OrchestratorInput.OrchestratorName)" $DurableRetryOptions = @{ FirstRetryInterval = (New-TimeSpan -Seconds 5) MaxNumberOfAttempts = if ($OrchestratorInput.MaxAttempts) { $OrchestratorInput.MaxAttempts } else { 1 } From 15800ae8986577b3127e866f4e7b23ef5f44c9ee Mon Sep 17 00:00:00 2001 From: Esco Date: Mon, 3 Mar 2025 13:31:59 +0100 Subject: [PATCH 119/167] chore: rename autopilot standards --- ...dardAPConfig.ps1 => Invoke-CIPPStandardAutopilotProfile.ps1} | 2 +- ...dardAPESP.ps1 => Invoke-CIPPStandardAutopilotStatusPage.ps1} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename Modules/CIPPCore/Public/Standards/{Invoke-CIPPStandardAPConfig.ps1 => Invoke-CIPPStandardAutopilotProfile.ps1} (97%) rename Modules/CIPPCore/Public/Standards/{Invoke-CIPPStandardAPESP.ps1 => Invoke-CIPPStandardAutopilotStatusPage.ps1} (95%) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPConfig.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotProfile.ps1 similarity index 97% rename from Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPConfig.ps1 rename to Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotProfile.ps1 index c9f10dd78b14..2bd64ae5aa8e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPConfig.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotProfile.ps1 @@ -1,4 +1,4 @@ -function Invoke-CIPPStandardAPConfig { +function Invoke-CIPPStandardAutopilotProfile { <# .FUNCTIONALITY Internal diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPESP.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotStatusPage.ps1 similarity index 95% rename from Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPESP.ps1 rename to Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotStatusPage.ps1 index 303a30afd009..caba85209fb4 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAPESP.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotStatusPage.ps1 @@ -1,4 +1,4 @@ -function Invoke-CIPPStandardAPESP { +function Invoke-CIPPStandardAutopilotStatusPage { <# .FUNCTIONALITY Internal From 6bb3d12bbe82e16d1f92f52ad547079a6f779e1e Mon Sep 17 00:00:00 2001 From: Esco Date: Mon, 3 Mar 2025 13:33:37 +0100 Subject: [PATCH 120/167] chore: update comment --- .../Invoke-CIPPStandardAutopilotProfile.ps1 | 38 ++++++++++++++++++- ...Invoke-CIPPStandardAutopilotStatusPage.ps1 | 34 ++++++++++++++++- 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotProfile.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotProfile.ps1 index 2bd64ae5aa8e..080b78ba5eab 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotProfile.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotProfile.ps1 @@ -1,7 +1,43 @@ function Invoke-CIPPStandardAutopilotProfile { <# .FUNCTIONALITY - Internal + Internal + .COMPONENT + (APIName) AutopilotProfile + .SYNOPSIS + (Label) Enable Autopilot Profile + .DESCRIPTION + (Helptext) Assign the appropriate Autopilot profile to streamline device deployment. + (DocsDescription) This standard allows the deployment of Autopilot profiles to devices, including settings such as unique name templates, language options, and local admin privileges. + .NOTES + CAT + Device Management Standards + TAG + DISABLEDFEATURES + + ADDEDCOMPONENT + {"type":"textField","name":"standards.AutopilotProfile.DisplayName","label":"Profile Display Name"} + {"type":"textField","name":"standards.AutopilotProfile.Description","label":"Profile Description"} + {"type":"textField","name":"standards.AutopilotProfile.DeviceNameTemplate","label":"Unique Device Name Template"} + {"type":"autoComplete","multiple":false,"creatable":false,"name":"standards.AutopilotProfile.Languages","label":"Languages","api":{"url":"/languageList.json","labelField":"language","valueField":"tag"}} + {"type":"switch","name":"standards.AutopilotProfile.CollectHash","label":"Convert all targeted devices to Autopilot","defaultValue":true} + {"type":"switch","name":"standards.AutopilotProfile.AssignToAllDevices","label":"Assign to all devices","defaultValue":true} + {"type":"switch","name":"standards.AutopilotProfile.SelfDeployingMode","label":"Enable Self-deploying Mode","defaultValue":true} + {"type":"switch","name":"standards.AutopilotProfile.HideTerms","label":"Hide Terms and Conditions","defaultValue":true} + {"type":"switch","name":"standards.AutopilotProfile.HidePrivacy","label":"Hide Privacy Settings","defaultValue":true} + {"type":"switch","name":"standards.AutopilotProfile.HideChangeAccount","label":"Hide Change Account Options","defaultValue":true} + {"type":"switch","name":"standards.AutopilotProfile.NotLocalAdmin","label":"Setup user as a standard user (not local admin)","defaultValue":true} + {"type":"switch","name":"standards.AutopilotProfile.AllowWhiteGlove","label":"Allow White Glove OOBE","defaultValue":true} + {"type":"switch","name":"standards.AutopilotProfile.AutoKeyboard","label":"Automatically configure keyboard","defaultValue":true} + IMPACT + Low Impact + ADDEDDATE + 2023-12-30 + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/ #> param($Tenant, $Settings) ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'APConfig' diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotStatusPage.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotStatusPage.ps1 index caba85209fb4..63d2bc635414 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotStatusPage.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotStatusPage.ps1 @@ -1,7 +1,39 @@ function Invoke-CIPPStandardAutopilotStatusPage { <# .FUNCTIONALITY - Internal + Internal + .COMPONENT + (APIName) AutopilotStatusPage + .SYNOPSIS + (Label) Enable Autopilot Status Page + .DESCRIPTION + (Helptext) Deploy the Autopilot Status Page, which shows progress during device setup through Autopilot. + (DocsDescription) This standard allows configuration of the Autopilot Status Page, providing users with a visual representation of the progress during device setup. It includes options like timeout, logging, and retry settings. + .NOTES + CAT + Device Management Standards + TAG + DISABLEDFEATURES + + ADDEDCOMPONENT + {"type":"number","name":"standards.AutopilotStatusPage.TimeOutInMinutes","label":"Timeout in minutes","defaultValue":60} + {"type":"textField","name":"standards.AutopilotStatusPage.ErrorMessage","label":"Custom Error Message","required":false} + {"type":"switch","name":"standards.AutopilotStatusPage.ShowProgress","label":"Show progress to users","defaultValue":true} + {"type":"switch","name":"standards.AutopilotStatusPage.EnableLog","label":"Turn on log collection","defaultValue":true} + {"type":"switch","name":"standards.AutopilotStatusPage.OBEEOnly","label":"Show status page only with OOBE setup","defaultValue":true} + {"type":"switch","name":"standards.AutopilotStatusPage.BlockDevice","label":"Block device usage during setup","defaultValue":true} + {"type":"switch","name":"standards.AutopilotStatusPage.AllowRetry","label":"Allow retry","defaultValue":true} + {"type":"switch","name":"standards.AutopilotStatusPage.AllowReset","label":"Allow reset","defaultValue":true} + {"type":"switch","name":"standards.AutopilotStatusPage.AllowFail","label":"Allow users to use device if setup fails","defaultValue":true} + IMPACT + Low Impact + ADDEDDATE + 2023-12-30 + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards/ #> param($Tenant, $Settings) If ($Settings.remediate -eq $true) { From 2bf638db9d3c51f5c5c4e7dfdd832448ddf56f79 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 13:34:32 +0100 Subject: [PATCH 121/167] more application insightys logging temporary --- host.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/host.json b/host.json index 4e9888399363..ae174a8b41b8 100644 --- a/host.json +++ b/host.json @@ -13,5 +13,19 @@ "maxConcurrentActivityFunctions": 1, "maxConcurrentOrchestratorFunctions": 1 } + }, + "logging": { + "logLevel": { + "default": "Trace", + "Host.Results": "Trace", + "Host.Aggregator": "Trace", + "Function": "Trace", + "Host.Executor": "Trace" + }, + "applicationInsights": { + "samplingSettings": { + "isEnabled": false + } + } } } From 46c59f68dad343da4b8d600f03d8e9a9e419f4eb Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 14:23:02 +0100 Subject: [PATCH 122/167] added troubleshooting --- Modules/CippEntrypoints/CippEntrypoints.psm1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/CippEntrypoints/CippEntrypoints.psm1 b/Modules/CippEntrypoints/CippEntrypoints.psm1 index 7c0a29c636fa..cf79a000feb0 100644 --- a/Modules/CippEntrypoints/CippEntrypoints.psm1 +++ b/Modules/CippEntrypoints/CippEntrypoints.psm1 @@ -133,6 +133,7 @@ function Receive-CippOrchestrationTrigger { function Receive-CippActivityTrigger { Param($Item) + Write-Warning "Hey Boo, the activity function is running. Here's some info: $($Item | ConvertTo-Json -Depth 10 -Compress)" try { $Start = Get-Date Set-Location (Get-Item $PSScriptRoot).Parent.Parent.FullName From 7441e0da11603325470d1725b8c59518aa91b3df Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 14:25:45 +0100 Subject: [PATCH 123/167] temporary write warning for app insihgts --- Modules/CippEntrypoints/CippEntrypoints.psm1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/CippEntrypoints/CippEntrypoints.psm1 b/Modules/CippEntrypoints/CippEntrypoints.psm1 index cf79a000feb0..4f71209cd7d3 100644 --- a/Modules/CippEntrypoints/CippEntrypoints.psm1 +++ b/Modules/CippEntrypoints/CippEntrypoints.psm1 @@ -158,8 +158,9 @@ function Receive-CippActivityTrigger { if ($Item.FunctionName) { $FunctionName = 'Push-{0}' -f $Item.FunctionName try { + Write-Warning "Activity starting Function: Push-$FunctionName." Invoke-Command -ScriptBlock { & $FunctionName -Item $Item } - + Write-Warning "Activity completed Function: Push-$FunctionName." if ($TaskStatus) { $QueueTask.Status = 'Completed' $null = Set-CippQueueTask @QueueTask From 32657cee6f193d6f50ebfaf637f7ba6d14ff08a2 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 15:02:16 +0100 Subject: [PATCH 124/167] fix return and data processing --- .../CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 index 5dac3d62d297..66f8abd1ee4c 100644 --- a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 @@ -16,7 +16,9 @@ function Test-CIPPAuditLogRules { # Get the CacheWebhooks table for removing processed rows $CacheWebhooksTable = Get-CippTable -TableName 'CacheWebhooks' - + #Replace $Rows which is an array of RowIds, with the actual data from the CacheWebhooks table + $Rows = Get-CIPPAzDataTableEntity @CacheWebhooksTable -Filter "PartitionKey eq '$TenantFilter'" | Where-Object { $_.RowKey -in $Rows } + Write-Host "Rows: $($Rows.Count)" $ExtendedPropertiesIgnoreList = @( 'OAuth2:Authorize' 'OAuth2:Token' @@ -55,7 +57,7 @@ function Test-CIPPAuditLogRules { if ($LogCount -gt 0) { $LocationTable = Get-CIPPTable -TableName 'knownlocationdb' $ProcessedData = foreach ($AuditRecord in $SearchResults) { - #Write-Host "Auditlogs: The record is $($AuditRecord.operation) - $($TenantFilter)" + Write-Host "Processing RowKey $($AuditRecord.id)" $RootProperties = $AuditRecord | Select-Object * -ExcludeProperty auditData $Data = $AuditRecord.auditData | Select-Object *, CIPPAction, CIPPClause, CIPPGeoLocation, CIPPBadRepIP, CIPPHostedIP, CIPPIPDetected, CIPPLocationInfo, CIPPExtendedProperties, CIPPDeviceProperties, CIPPParameters, CIPPModifiedProperties, AuditRecord -ErrorAction SilentlyContinue try { @@ -235,4 +237,6 @@ function Test-CIPPAuditLogRules { } catch { Write-Information "Error removing rows from cache: $($_.Exception.Message)" } + + return $Results } From 0ca0c750ed913f1e8c5a87bb79a888cc352360ad Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 15:19:42 +0100 Subject: [PATCH 125/167] small revert. --- Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 index 66f8abd1ee4c..2350969f802d 100644 --- a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 @@ -16,9 +16,7 @@ function Test-CIPPAuditLogRules { # Get the CacheWebhooks table for removing processed rows $CacheWebhooksTable = Get-CippTable -TableName 'CacheWebhooks' - #Replace $Rows which is an array of RowIds, with the actual data from the CacheWebhooks table - $Rows = Get-CIPPAzDataTableEntity @CacheWebhooksTable -Filter "PartitionKey eq '$TenantFilter'" | Where-Object { $_.RowKey -in $Rows } - Write-Host "Rows: $($Rows.Count)" + $ExtendedPropertiesIgnoreList = @( 'OAuth2:Authorize' 'OAuth2:Token' From bc81c51961df69873c339e60ed4a260b618c1426 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 15:21:26 +0100 Subject: [PATCH 126/167] added clean exit --- .../Activity Triggers/Webhooks/Push-AuditLogTenantProcess.ps1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenantProcess.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenantProcess.ps1 index 8c3cd08297aa..086adcaf37dc 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenantProcess.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenantProcess.ps1 @@ -20,8 +20,10 @@ function Push-AuditLogTenantProcess { if ($Rows.Count -gt 0) { Write-Information "Retrieved $($Rows.Count) rows from cache for processing" Test-CIPPAuditLogRules -TenantFilter $TenantFilter -Rows $Rows + exit 0 } else { Write-Information 'No rows found in cache for the provided row IDs' + exit 0 } } catch { Write-Information ('Push-AuditLogTenant: Error {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message) From d6701b642879263a176ff2baa7e88266e1731508 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 15:23:27 +0100 Subject: [PATCH 127/167] add logging --- .../Orchestrator Functions/Start-AuditLogOrchestrator.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 index 9de12f33de69..92be8a232a9d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 @@ -41,8 +41,8 @@ function Start-AuditLogOrchestrator { $TenantFilter = $TenantGroup.Name $RowIds = $TenantGroup.Group.RowKey for ($i = 0; $i -lt $RowIds.Count; $i += 1000) { + Write-Host "Processing $TenantFilter with $($RowIds.Count) row IDs. We're processing id $($RowIds[$i]) to $($RowIds[[Math]::Min($i + 999, $RowIds.Count - 1)])" $BatchRowIds = $RowIds[$i..([Math]::Min($i + 999, $RowIds.Count - 1))] - [PSCustomObject]@{ TenantFilter = $TenantFilter RowIds = $BatchRowIds From be2916d085badd906bdb9add06aad0fdbf20b89c Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 3 Mar 2025 10:21:15 -0500 Subject: [PATCH 128/167] add returns in cippentrypoints also add help comments --- Modules/CippEntrypoints/CippEntrypoints.psm1 | 45 +++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/Modules/CippEntrypoints/CippEntrypoints.psm1 b/Modules/CippEntrypoints/CippEntrypoints.psm1 index 4f71209cd7d3..1b8732c5b702 100644 --- a/Modules/CippEntrypoints/CippEntrypoints.psm1 +++ b/Modules/CippEntrypoints/CippEntrypoints.psm1 @@ -2,8 +2,16 @@ using namespace System.Net function Receive-CippHttpTrigger { <# + .SYNOPSIS + Execute HTTP trigger function + .DESCRIPTION + Execute HTTP trigger function from an azure function app + .PARAMETER Request + The request object from the function app + .PARAMETER TriggerMetadata + The trigger metadata object from the function app .FUNCTIONALITY - Entrypoint + Entrypoint #> Param( $Request, @@ -62,8 +70,18 @@ function Receive-CippHttpTrigger { } function Receive-CippOrchestrationTrigger { + <# + .SYNOPSIS + Execute durable orchestrator function + .DESCRIPTION + Execute orchestrator from azure function app + .PARAMETER Context + The context object from the function app + .FUNCTIONALITY + Entrypoint + #> param($Context) - + try { if (Test-Json -Json $Context.Input) { $OrchestratorInput = $Context.Input | ConvertFrom-Json @@ -129,9 +147,20 @@ function Receive-CippOrchestrationTrigger { } catch { Write-Information "Orchestrator error $($_.Exception.Message) line $($_.InvocationInfo.ScriptLineNumber)" } + return $true } function Receive-CippActivityTrigger { + <# + .SYNOPSIS + Execute durable activity function + .DESCRIPTION + Execute durable activity function from an orchestrator + .PARAMETER Item + The item to process + .FUNCTIONALITY + Entrypoint + #> Param($Item) Write-Warning "Hey Boo, the activity function is running. Here's some info: $($Item | ConvertTo-Json -Depth 10 -Compress)" try { @@ -201,9 +230,20 @@ function Receive-CippActivityTrigger { $null = Set-CippQueueTask @QueueTask } } + return $true } function Receive-CIPPTimerTrigger { + <# + .SYNOPSIS + This function is used to execute timer functions based on the cron schedule. + .DESCRIPTION + This function is used to execute timer functions based on the cron schedule. + .PARAMETER Timer + The timer trigger object from the function app + .FUNCTIONALITY + Entrypoint + #> param($Timer) $UtcNow = (Get-Date).ToUniversalTime() @@ -257,6 +297,7 @@ function Receive-CIPPTimerTrigger { Add-CIPPAzDataTableEntity @Table -Entity $FunctionStatus -Force } + return $true } Export-ModuleMember -Function @('Receive-CippHttpTrigger', 'Receive-CippOrchestrationTrigger', 'Receive-CippActivityTrigger', 'Receive-CIPPTimerTrigger') From cb01749c9e3c98afe5e23124cc03acc3dc00ed81 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 16:24:02 +0100 Subject: [PATCH 129/167] timing logging --- .../New-CIPPAuditLogSearchResultsCache.ps1 | 2 +- .../Public/Webhooks/Test-CIPPAuditLogRules.ps1 | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 b/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 index ea00d38cbe48..76701ac05736 100644 --- a/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 +++ b/Modules/CIPPCore/Public/AuditLogs/New-CIPPAuditLogSearchResultsCache.ps1 @@ -74,7 +74,7 @@ function New-CIPPAuditLogSearchResultsCache { $FailedDownloadsTable = Get-CippTable -TableName 'FailedAuditLogDownloads' $failedEntities = Get-CIPPAzDataTableEntity @FailedDownloadsTable -Filter "PartitionKey eq '$TenantFilter' and SearchId eq '$SearchId'" if ($failedEntities) { - Remove-AzDataTableEntity @FailedDownloadsTable -Entity $failedEntities + Remove-AzDataTableEntity @FailedDownloadsTable -Entity $failedEntities -Force Write-Information "Removed failed download records for search ID: $SearchId, tenant: $TenantFilter" } } catch { diff --git a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 index 2350969f802d..11ab41e6a4db 100644 --- a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 @@ -7,6 +7,8 @@ function Test-CIPPAuditLogRules { $Rows ) + $FunctionStartTime = Get-Date + $Results = [PSCustomObject]@{ TotalLogs = 0 MatchedLogs = 0 @@ -55,6 +57,7 @@ function Test-CIPPAuditLogRules { if ($LogCount -gt 0) { $LocationTable = Get-CIPPTable -TableName 'knownlocationdb' $ProcessedData = foreach ($AuditRecord in $SearchResults) { + $RecordStartTime = Get-Date Write-Host "Processing RowKey $($AuditRecord.id)" $RootProperties = $AuditRecord | Select-Object * -ExcludeProperty auditData $Data = $AuditRecord.auditData | Select-Object *, CIPPAction, CIPPClause, CIPPGeoLocation, CIPPBadRepIP, CIPPHostedIP, CIPPIPDetected, CIPPLocationInfo, CIPPExtendedProperties, CIPPDeviceProperties, CIPPParameters, CIPPModifiedProperties, AuditRecord -ErrorAction SilentlyContinue @@ -102,7 +105,12 @@ function Test-CIPPAuditLogRules { $Trusted = $true } if (!$Trusted) { + $CacheLookupStartTime = Get-Date $Location = Get-CIPPAzDataTableEntity @LocationTable -Filter "RowKey eq '$($Data.clientIp)'" | Select-Object -Last 1 + $CacheLookupEndTime = Get-Date + $CacheLookupSeconds = ($CacheLookupEndTime - $CacheLookupStartTime).TotalSeconds + Write-Warning "Cache lookup for IP $($Data.clientip) took $CacheLookupSeconds seconds" + if ($Location) { $Country = $Location.CountryOrRegion $City = $Location.City @@ -111,7 +119,11 @@ function Test-CIPPAuditLogRules { $ASName = $Location.ASName } else { try { + $IPLookupStartTime = Get-Date $Location = Get-CIPPGeoIPLocation -IP $Data.clientip + $IPLookupEndTime = Get-Date + $IPLookupSeconds = ($IPLookupEndTime - $IPLookupStartTime).TotalSeconds + Write-Warning "IP lookup for $($Data.clientip) took $IPLookupSeconds seconds" } catch { #write-warning "Unable to get IP location for $($Data.clientip): $($_.Exception.Message)" } @@ -151,6 +163,9 @@ function Test-CIPPAuditLogRules { #write-warning "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 } + $RecordEndTime = Get-Date + $RecordSeconds = ($RecordEndTime - $RecordStartTime).TotalSeconds + Write-Warning "Task took $RecordSeconds seconds for RowKey $($AuditRecord.id)" } #write-warning "Processed Data: $(($ProcessedData | Measure-Object).Count) - This should be higher than 0 in many cases, because the where object has not run yet." #write-warning "Creating filters - $(($ProcessedData.operation | Sort-Object -Unique) -join ',') - $($TenantFilter)" From f90ade1b6766fb4798252826f2f7f51cfd5bddf9 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 16:25:09 +0100 Subject: [PATCH 130/167] lkog timings to see whats going on --- Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 index 11ab41e6a4db..9ccb6e21a2cf 100644 --- a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 @@ -198,6 +198,7 @@ function Test-CIPPAuditLogRules { $MatchedRules = [System.Collections.Generic.List[string]]::new() $DataToProcess = foreach ($clause in $Where) { + $ClauseStartTime = Get-Date Write-Warning "Webhook: Processing clause: $($clause.clause)" $ReturnedData = $ProcessedData | Where-Object { Invoke-Expression $clause.clause } if ($ReturnedData) { @@ -209,6 +210,9 @@ function Test-CIPPAuditLogRules { $item } } + $ClauseEndTime = Get-Date + $ClauseSeconds = ($ClauseEndTime - $ClauseStartTime).TotalSeconds + Write-Warning "Task took $ClauseSeconds seconds for clause: $($clause.clause)" $ReturnedData } $Results.MatchedRules = @($MatchedRules | Select-Object -Unique) From 37c94ac55c7eab1e007a6d5cfded3556b0cad8db Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 16:41:07 +0100 Subject: [PATCH 131/167] move to new knownip table. --- Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 index 9ccb6e21a2cf..8c6bb9b79a1d 100644 --- a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 @@ -55,7 +55,7 @@ function Test-CIPPAuditLogRules { } if ($LogCount -gt 0) { - $LocationTable = Get-CIPPTable -TableName 'knownlocationdb' + $LocationTable = Get-CIPPTable -TableName 'knownlocationdbv2' $ProcessedData = foreach ($AuditRecord in $SearchResults) { $RecordStartTime = Get-Date Write-Host "Processing RowKey $($AuditRecord.id)" @@ -135,7 +135,7 @@ function Test-CIPPAuditLogRules { $IP = $Data.ClientIP $LocationInfo = @{ RowKey = [string]$Data.clientip - PartitionKey = [string]$Data.id + PartitionKey = 'ip' Tenant = [string]$TenantFilter CountryOrRegion = "$Country" City = "$City" From ebef5516041090b21edd7c02daefe2bd47e788b6 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 3 Mar 2025 11:20:59 -0500 Subject: [PATCH 132/167] chore: refactor cache cleanups --- .../Tenant/Invoke-ListTenants.ps1 | 11 +++++--- .../Timer Functions/Start-TableCleanup.ps1 | 20 ++++++++++++++ .../Public/GraphHelper/Remove-CIPPCache.ps1 | 26 ++++++++++++------- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-ListTenants.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-ListTenants.ps1 index 1fd2fd8f97a8..0f432d56e54d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-ListTenants.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-ListTenants.ps1 @@ -23,8 +23,8 @@ Function Invoke-ListTenants { } # Clear Cache - if ($Request.Query.ClearCache -eq $true) { - Remove-CIPPCache -tenantsOnly $Request.Query.TenantsOnly + if ($Request.Body.ClearCache -eq $true) { + $Results = Remove-CIPPCache -tenantsOnly $Request.Body.TenantsOnly $InputObject = [PSCustomObject]@{ Batch = @( @@ -40,7 +40,12 @@ Function Invoke-ListTenants { $GraphRequest = [pscustomobject]@{'Results' = 'Cache has been cleared and a tenant refresh is queued.' } Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK - Body = $GraphRequest + Body = @{ + Results = @($GraphRequest) + Metadata = @{ + Details = $Results + } + } }) #Get-Tenants -IncludeAll -TriggerRefresh return diff --git a/Modules/CIPPCore/Public/Entrypoints/Timer Functions/Start-TableCleanup.ps1 b/Modules/CIPPCore/Public/Entrypoints/Timer Functions/Start-TableCleanup.ps1 index 21dcd6a7e9aa..ba15c02add60 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Timer Functions/Start-TableCleanup.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Timer Functions/Start-TableCleanup.ps1 @@ -48,7 +48,27 @@ function Start-TableCleanup { } ) + $DeleteTables = @( + 'knownlocationdb' + ) + if ($PSCmdlet.ShouldProcess('Start-TableCleanup', 'Starting Table Cleanup')) { + foreach ($Table in $DeleteTables) { + try { + $Table = Get-CIPPTable -tablename $Table + if ($Table) { + Write-Information "Deleting table $($Table.Context.TableName)" + try { + Remove-AzDataTable -Context $Table.Context -Force + } catch { + Write-LogMessage -API 'TableCleanup' -message "Failed to delete table $($Table.Context.TableName)" -sev Error -LogData (Get-CippException -Exception $_) + } + } + } catch { + Write-Information "Table $Table not found" + } + } + Write-Information 'Starting table cleanup' foreach ($Rule in $CleanupRules) { if ($Rule.Where) { diff --git a/Modules/CIPPCore/Public/GraphHelper/Remove-CIPPCache.ps1 b/Modules/CIPPCore/Public/GraphHelper/Remove-CIPPCache.ps1 index e9e7380906dd..9dca6bdc7b1f 100644 --- a/Modules/CIPPCore/Public/GraphHelper/Remove-CIPPCache.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/Remove-CIPPCache.ps1 @@ -13,28 +13,36 @@ function Remove-CIPPCache { if ($ClearIncludedTenants) { Remove-AzDataTableEntity -Force @TenantsTable -Entity $ClearIncludedTenants } + "Removed $($ClearIncludedTenants.Count) tenants" - if ($TenantsOnly -eq 'false') { - Write-Host 'Clearing all' + if ($TenantsOnly -eq $false) { + 'Clearing all cached table data' + $Context = New-AzDataTableContext -ConnectionString $env:AzureWebJobsStorage + $Tables = Get-AzDataTable -Context $Context + foreach ($Table in $Tables) { + if ($Table -match '^cache') { + "Removing cache table $Table" + $TableContext = Get-CIPPTable -TableName $Table + Remove-AzDataTable @TableContext + } + } + + 'Clearing domain analyser results' # Remove Domain Analyser cached results $DomainsTable = Get-CippTable -tablename 'Domains' $Filter = "PartitionKey eq 'TenantDomains'" $ClearDomainAnalyserRows = Get-CIPPAzDataTableEntity @DomainsTable -Filter $Filter | ForEach-Object { - $_.DomainAnalyser = '' + $_ | Add-Member -MemberType NoteProperty -Name DomainAnalyser -Value '' -Force $_ } if ($ClearDomainAnalyserRows) { Update-AzDataTableEntity -Force @DomainsTable -Entity $ClearDomainAnalyserRows } - #Clear BPA - $BPATable = Get-CippTable -tablename 'cachebpav2' - $ClearBPARows = Get-CIPPAzDataTableEntity @BPATable - if ($ClearBPARows) { - Remove-AzDataTableEntity -Force @BPATable -Entity $ClearBPARows - } + $ENV:SetFromProfile = $null $Script:SkipListCache = $Null $Script:SkipListCacheEmpty = $Null $Script:IncludedTenantsCache = $Null } + 'Cache cleanup complete' } From 603b6ed111678effdda70deac6db2e0d915f3b82 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 17:31:42 +0100 Subject: [PATCH 133/167] force array if row is single item --- Modules/CIPPCore/Public/Entrypoints/Invoke-ListKnownIPDb.ps1 | 2 +- .../Orchestrator Functions/Start-AuditLogOrchestrator.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListKnownIPDb.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListKnownIPDb.ps1 index e336eddbc938..0f666d3fce64 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListKnownIPDb.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListKnownIPDb.ps1 @@ -16,7 +16,7 @@ Function Invoke-ListKnownIPDb { # Write to the Azure Functions log stream. Write-Host 'PowerShell HTTP trigger function processed a request.' - $Table = Get-CIPPTable -TableName 'knownlocationdb' + $Table = Get-CIPPTable -TableName 'knownlocationdbv2' $Filter = "Tenant eq '$($Request.Query.TenantFilter)'" $KnownIPDb = Get-CIPPAzDataTableEntity @Table -Filter $Filter diff --git a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 index 92be8a232a9d..a0c30e7133bc 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 @@ -39,7 +39,7 @@ function Start-AuditLogOrchestrator { $ProcessQueue = New-CippQueueEntry -Name 'Audit Logs Process' -Reference 'AuditLogsProcess' -TotalTasks ($TenantGroups | Measure-Object -Property Count -Sum).Sum $ProcessBatch = foreach ($TenantGroup in $TenantGroups) { $TenantFilter = $TenantGroup.Name - $RowIds = $TenantGroup.Group.RowKey + $RowIds = @($TenantGroup.Group.RowKey) for ($i = 0; $i -lt $RowIds.Count; $i += 1000) { Write-Host "Processing $TenantFilter with $($RowIds.Count) row IDs. We're processing id $($RowIds[$i]) to $($RowIds[[Math]::Min($i + 999, $RowIds.Count - 1)])" $BatchRowIds = $RowIds[$i..([Math]::Min($i + 999, $RowIds.Count - 1))] From d3db068336b037c25e544c0ebef9da3317e02e56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 3 Mar 2025 17:40:30 +0100 Subject: [PATCH 134/167] Unsure what im comiting here --- .../Invoke-EditAntiPhishingFilter.ps1 | 114 +++++++++--------- .../Invoke-EditMalwareFilter.ps1 | 114 +++++++++--------- .../Invoke-EditSafeAttachmentsFilter.ps1 | 114 +++++++++--------- .../Invoke-EditSafeLinksFilter.ps1 | 114 +++++++++--------- 4 files changed, 228 insertions(+), 228 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditAntiPhishingFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditAntiPhishingFilter.ps1 index 86f787e74d1a..002f78839f1b 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditAntiPhishingFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditAntiPhishingFilter.ps1 @@ -1,57 +1,57 @@ -function Invoke-EditAntiPhishingFilter { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.SpamFilter.Read - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - $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. - $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter - $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName - $State = $Request.Query.State ?? $Request.Body.State - - try { - $ExoRequestParam = @{ - tenantid = $TenantFilter - cmdParams = @{ - Identity = $RuleName - } - useSystemMailbox = $true - } - - switch ($State) { - 'Enable' { - $ExoRequestParam.Add('cmdlet', 'Enable-AntiPhishRule') - } - 'Disable' { - $ExoRequestParam.Add('cmdlet', 'Disable-AntiPhishRule') - } - Default { - throw 'Invalid state' - } - } - $null = New-ExoRequest @ExoRequestParam - - $Result = "Successfully set Anti-Phishing rule $RuleName to $State" - Write-LogMessage -headers $Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev Info - $StatusCode = [HttpStatusCode]::OK - } catch { - $ErrorMessage = Get-CippException -Exception $_ - $Result = "Failed setting Anti-Phishing rule $RuleName to $State. Error: $($ErrorMessage.NormalizedError)" - Write-LogMessage -headers $Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage - $StatusCode = [HttpStatusCode]::InternalServerError - } - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $StatusCode - Body = @{Results = $Result } - }) -} +function Invoke-EditAntiPhishingFilter { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.SpamFilter.Read + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $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. + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName + $State = $Request.Query.State ?? $Request.Body.State + + try { + $ExoRequestParam = @{ + tenantid = $TenantFilter + cmdParams = @{ + Identity = $RuleName + } + useSystemMailbox = $true + } + + switch ($State) { + 'Enable' { + $ExoRequestParam.Add('cmdlet', 'Enable-AntiPhishRule') + } + 'Disable' { + $ExoRequestParam.Add('cmdlet', 'Disable-AntiPhishRule') + } + Default { + throw 'Invalid state' + } + } + $null = New-ExoRequest @ExoRequestParam + + $Result = "Successfully set Anti-Phishing rule $RuleName to $State" + Write-LogMessage -headers $Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev Info + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed setting Anti-Phishing rule $RuleName to $State. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError + } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @{Results = $Result } + }) +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditMalwareFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditMalwareFilter.ps1 index fb1943714bf4..bb599a80f6f3 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditMalwareFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditMalwareFilter.ps1 @@ -1,57 +1,57 @@ -function Invoke-EditMalwareFilter { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.SpamFilter.Read - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - $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. - $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter - $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName - $State = $Request.Query.State ?? $Request.Body.State - - try { - $ExoRequestParam = @{ - tenantid = $TenantFilter - cmdParams = @{ - Identity = $RuleName - } - useSystemMailbox = $true - } - - switch ($State) { - 'Enable' { - $ExoRequestParam.Add('cmdlet', 'Enable-MalwareFilterRule') - } - 'Disable' { - $ExoRequestParam.Add('cmdlet', 'Disable-MalwareFilterRule') - } - Default { - throw 'Invalid state' - } - } - $null = New-ExoRequest @ExoRequestParam - - $Result = "Successfully set Malware Filter rule $($RuleName) to $($State)" - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev Info - $StatusCode = [HttpStatusCode]::OK - } catch { - $ErrorMessage = Get-CippException -Exception $_ - $Result = "Failed setting Malware Filter rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage - $StatusCode = [HttpStatusCode]::InternalServerError - } - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $StatusCode - Body = @{Results = $Result } - }) -} +function Invoke-EditMalwareFilter { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.SpamFilter.Read + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $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. + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName + $State = $Request.Query.State ?? $Request.Body.State + + try { + $ExoRequestParam = @{ + tenantid = $TenantFilter + cmdParams = @{ + Identity = $RuleName + } + useSystemMailbox = $true + } + + switch ($State) { + 'Enable' { + $ExoRequestParam.Add('cmdlet', 'Enable-MalwareFilterRule') + } + 'Disable' { + $ExoRequestParam.Add('cmdlet', 'Disable-MalwareFilterRule') + } + Default { + throw 'Invalid state' + } + } + $null = New-ExoRequest @ExoRequestParam + + $Result = "Successfully set Malware Filter rule $($RuleName) to $($State)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev Info + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed setting Malware Filter rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError + } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @{Results = $Result } + }) +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeAttachmentsFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeAttachmentsFilter.ps1 index a6eae5585946..1adb00b34010 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeAttachmentsFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeAttachmentsFilter.ps1 @@ -1,57 +1,57 @@ -function Invoke-EditSafeAttachmentsFilter { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.SpamFilter.Read - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - $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. - $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter - $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName - $State = $Request.Query.State ?? $Request.Body.State - - try { - $ExoRequestParam = @{ - tenantid = $TenantFilter - cmdParams = @{ - Identity = $RuleName - } - useSystemMailbox = $true - } - - switch ($State) { - 'Enable' { - $ExoRequestParam.Add('cmdlet', 'Enable-SafeAttachmentRule') - } - 'Disable' { - $ExoRequestParam.Add('cmdlet', 'Disable-SafeAttachmentRule') - } - Default { - throw 'Invalid state' - } - } - $null = New-ExoRequest @ExoRequestParam - - $Result = "Successfully set SafeAttachment rule $($RuleName) to $($State)" - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Info' - $StatusCode = [HttpStatusCode]::OK - } catch { - $ErrorMessage = Get-CippException -Exception $_ - $Result = "Failed setting SafeAttachment rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage - $StatusCode = [HttpStatusCode]::InternalServerError - } - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $StatusCode - Body = @{Results = $Result } - }) -} +function Invoke-EditSafeAttachmentsFilter { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.SpamFilter.Read + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $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. + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName + $State = $Request.Query.State ?? $Request.Body.State + + try { + $ExoRequestParam = @{ + tenantid = $TenantFilter + cmdParams = @{ + Identity = $RuleName + } + useSystemMailbox = $true + } + + switch ($State) { + 'Enable' { + $ExoRequestParam.Add('cmdlet', 'Enable-SafeAttachmentRule') + } + 'Disable' { + $ExoRequestParam.Add('cmdlet', 'Disable-SafeAttachmentRule') + } + Default { + throw 'Invalid state' + } + } + $null = New-ExoRequest @ExoRequestParam + + $Result = "Successfully set SafeAttachment rule $($RuleName) to $($State)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed setting SafeAttachment rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError + } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @{Results = $Result } + }) +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeLinksFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeLinksFilter.ps1 index 89141c9f413e..fd7b11144b48 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeLinksFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeLinksFilter.ps1 @@ -1,57 +1,57 @@ -function Invoke-EditSafeLinksFilter { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.SpamFilter.Read - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - $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. - $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter - $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName - $State = $Request.Query.State ?? $Request.Body.State - - try { - $ExoRequestParam = @{ - tenantid = $TenantFilter - cmdParams = @{ - Identity = $RuleName - } - useSystemMailbox = $true - } - - switch ($State) { - 'Enable' { - $ExoRequestParam.Add('cmdlet', 'Enable-SafeLinksRule') - } - 'Disable' { - $ExoRequestParam.Add('cmdlet', 'Disable-SafeLinksRule') - } - Default { - throw 'Invalid state' - } - } - $null = New-ExoRequest @ExoRequestParam - - $Result = "Successfully set SafeLinks rule $($RuleName) to $($State)" - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev Info - $StatusCode = [HttpStatusCode]::OK - } catch { - $ErrorMessage = Get-CippException -Exception $_ - $Result = "Failed setting SafeLinks rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' - $StatusCode = [HttpStatusCode]::InternalServerError - } - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $StatusCode - Body = @{Results = $Result } - }) -} +function Invoke-EditSafeLinksFilter { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.SpamFilter.Read + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $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. + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName + $State = $Request.Query.State ?? $Request.Body.State + + try { + $ExoRequestParam = @{ + tenantid = $TenantFilter + cmdParams = @{ + Identity = $RuleName + } + useSystemMailbox = $true + } + + switch ($State) { + 'Enable' { + $ExoRequestParam.Add('cmdlet', 'Enable-SafeLinksRule') + } + 'Disable' { + $ExoRequestParam.Add('cmdlet', 'Disable-SafeLinksRule') + } + Default { + throw 'Invalid state' + } + } + $null = New-ExoRequest @ExoRequestParam + + $Result = "Successfully set SafeLinks rule $($RuleName) to $($State)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev Info + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed setting SafeLinks rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' + $StatusCode = [HttpStatusCode]::InternalServerError + } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @{Results = $Result } + }) +} From ebae19811fb87bbdd5f73e1ef5b007c7f6822f6a Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 3 Mar 2025 12:09:15 -0500 Subject: [PATCH 135/167] fix: scheduled tasks with limited tenant list --- .../CIPP/Scheduler/Invoke-ListScheduledItems.ps1 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 025e8516b05a..01f7a7d1f2c0 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 @@ -49,8 +49,11 @@ Function Invoke-ListScheduledItems { } $AllowedTenants = Test-CIPPAccess -Request $Request -TenantList + if ($AllowedTenants -notcontains 'AllTenants') { - $Tasks = $Tasks | Where-Object -Property TenantId -In $AllowedTenants + $TenantList = Get-Tenants -IncludeErrors | Select-Object customerId, defaultDomainName + $AllowedTenantDomains = $TenantList | Where-Object -Property customerId -In $AllowedTenants | Select-Object -ExpandProperty defaultDomainName + $Tasks = $Tasks | Where-Object -Property Tenant -In $AllowedTenantDomains } $ScheduledTasks = foreach ($Task in $tasks) { if ($Task.Parameters) { From 9964f2dcf653af41520b3cc212f87f817125b868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 3 Mar 2025 18:24:13 +0100 Subject: [PATCH 136/167] feat: add support for auto-expanding archive in mailbox management --- .../Invoke-ExecEnableArchive.ps1 | 37 +++++++++++++++++++ .../Invoke-ExecEnableAutoExpandingArchive.ps1 | 32 ++++++++++++++++ .../Public/Set-CIPPMailboxArchive.ps1 | 24 ++++++++---- 3 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEnableArchive.ps1 create mode 100644 Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEnableAutoExpandingArchive.ps1 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEnableArchive.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEnableArchive.ps1 new file mode 100644 index 000000000000..bfb8cc74ad62 --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEnableArchive.ps1 @@ -0,0 +1,37 @@ +using namespace System.Net + +Function Invoke-ExecEnableArchive { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.Mailbox.ReadWrite + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $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. + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $ID = $Request.Query.id ?? $Request.Body.id + $UserName = $Request.Query.username ?? $Request.Body.username + + Try { + $ResultsArch = Set-CIPPMailboxArchive -userid $ID -tenantFilter $TenantFilter -APIName $APIName -Headers $Headers -ArchiveEnabled $true -Username $UserName + if ($ResultsArch -like 'Failed to set archive*') { throw $ResultsArch } + $StatusCode = [HttpStatusCode]::OK + } catch { + $ResultsArch = $_.Exception.Message + $StatusCode = [HttpStatusCode]::InternalServerError + } + $Results = [pscustomobject]@{'Results' = "$ResultsArch" } + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = $Results + }) + +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEnableAutoExpandingArchive.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEnableAutoExpandingArchive.ps1 new file mode 100644 index 000000000000..47eae36f8e60 --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEnableAutoExpandingArchive.ps1 @@ -0,0 +1,32 @@ +function Invoke-ExecEnableAutoExpandingArchive { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.Mailbox.ReadWrite + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $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. + $ID = $Request.Body.ID + $TenantFilter = $Request.Body.tenantFilter + $Username = $Request.Body.username + + try { + $Result = Set-CIPPMailboxArchive -TenantFilter $TenantFilter -UserID $ID -Username $Username -Headers $Headers -AutoExpandingArchive + $StatusCode = [HttpStatusCode]::OK + } catch { + $Result = $_.Exception.Message + $StatusCode = [HttpStatusCode]::InternalServerError + } + + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @{Results = "$Result" } + }) +} diff --git a/Modules/CIPPCore/Public/Set-CIPPMailboxArchive.ps1 b/Modules/CIPPCore/Public/Set-CIPPMailboxArchive.ps1 index 134dd48fb958..e20ee118a99a 100644 --- a/Modules/CIPPCore/Public/Set-CIPPMailboxArchive.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPMailboxArchive.ps1 @@ -6,19 +6,27 @@ function Set-CIPPMailboxArchive { $Username, $APIName = 'Mailbox Archive', $TenantFilter, - [bool]$ArchiveEnabled + [bool]$ArchiveEnabled, + [switch]$AutoExpandingArchive ) try { - if (!$Username) { $Username = $UserID } - $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Enable-Mailbox' -cmdParams @{Identity = $UserID; Archive = $ArchiveEnabled } - $Message = "Successfully set archive for $Username to $ArchiveEnabled" - Write-LogMessage -Headers $Headers -API $APINAME -tenant $TenantFilter -message $Message -Sev 'Info' + if ([string]::IsNullOrWhiteSpace($Username)) { $Username = $UserID } + $OperationType = if ($AutoExpandingArchive.IsPresent -eq $true) { 'auto-expanding archive' } else { 'archive' } + if ($AutoExpandingArchive.IsPresent -eq $true) { + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Enable-Mailbox' -cmdParams @{Identity = $UserID; AutoExpandingArchive = $true } + $Message = "Successfully enabled $OperationType for $Username" + } else { + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Enable-Mailbox' -cmdParams @{Identity = $UserID; Archive = $ArchiveEnabled } + $Message = "Successfully set $OperationType for $Username to $ArchiveEnabled" + } + + Write-LogMessage -Headers $Headers -API $APIName -tenant $TenantFilter -message $Message -Sev 'Info' return $Message } catch { $ErrorMessage = Get-CippException -Exception $_ - $Message = "Failed to set archive for $Username. Error: $($ErrorMessage.NormalizedError)" - Write-LogMessage -Headers $Headers -API $APINAME -tenant $TenantFilter -message $Message -Sev 'Error' -LogData $ErrorMessage - return $Message + $Message = "Failed to set $OperationType for $Username. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Headers -API $APIName -tenant $TenantFilter -message $Message -Sev 'Error' -LogData $ErrorMessage + throw $Message } } From 1d62c7e93b140da90ac78a60d3a7eee177b16a69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 3 Mar 2025 18:29:11 +0100 Subject: [PATCH 137/167] Revert "Unsure what im comiting here" This reverts commit d3db068336b037c25e544c0ebef9da3317e02e56. --- .../Invoke-EditAntiPhishingFilter.ps1 | 114 +++++++++--------- .../Invoke-EditMalwareFilter.ps1 | 114 +++++++++--------- .../Invoke-EditSafeAttachmentsFilter.ps1 | 114 +++++++++--------- .../Invoke-EditSafeLinksFilter.ps1 | 114 +++++++++--------- 4 files changed, 228 insertions(+), 228 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditAntiPhishingFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditAntiPhishingFilter.ps1 index 002f78839f1b..86f787e74d1a 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditAntiPhishingFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditAntiPhishingFilter.ps1 @@ -1,57 +1,57 @@ -function Invoke-EditAntiPhishingFilter { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.SpamFilter.Read - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - $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. - $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter - $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName - $State = $Request.Query.State ?? $Request.Body.State - - try { - $ExoRequestParam = @{ - tenantid = $TenantFilter - cmdParams = @{ - Identity = $RuleName - } - useSystemMailbox = $true - } - - switch ($State) { - 'Enable' { - $ExoRequestParam.Add('cmdlet', 'Enable-AntiPhishRule') - } - 'Disable' { - $ExoRequestParam.Add('cmdlet', 'Disable-AntiPhishRule') - } - Default { - throw 'Invalid state' - } - } - $null = New-ExoRequest @ExoRequestParam - - $Result = "Successfully set Anti-Phishing rule $RuleName to $State" - Write-LogMessage -headers $Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev Info - $StatusCode = [HttpStatusCode]::OK - } catch { - $ErrorMessage = Get-CippException -Exception $_ - $Result = "Failed setting Anti-Phishing rule $RuleName to $State. Error: $($ErrorMessage.NormalizedError)" - Write-LogMessage -headers $Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage - $StatusCode = [HttpStatusCode]::InternalServerError - } - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $StatusCode - Body = @{Results = $Result } - }) -} +function Invoke-EditAntiPhishingFilter { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.SpamFilter.Read + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $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. + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName + $State = $Request.Query.State ?? $Request.Body.State + + try { + $ExoRequestParam = @{ + tenantid = $TenantFilter + cmdParams = @{ + Identity = $RuleName + } + useSystemMailbox = $true + } + + switch ($State) { + 'Enable' { + $ExoRequestParam.Add('cmdlet', 'Enable-AntiPhishRule') + } + 'Disable' { + $ExoRequestParam.Add('cmdlet', 'Disable-AntiPhishRule') + } + Default { + throw 'Invalid state' + } + } + $null = New-ExoRequest @ExoRequestParam + + $Result = "Successfully set Anti-Phishing rule $RuleName to $State" + Write-LogMessage -headers $Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev Info + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed setting Anti-Phishing rule $RuleName to $State. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APINAME -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError + } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @{Results = $Result } + }) +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditMalwareFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditMalwareFilter.ps1 index bb599a80f6f3..fb1943714bf4 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditMalwareFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditMalwareFilter.ps1 @@ -1,57 +1,57 @@ -function Invoke-EditMalwareFilter { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.SpamFilter.Read - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - $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. - $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter - $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName - $State = $Request.Query.State ?? $Request.Body.State - - try { - $ExoRequestParam = @{ - tenantid = $TenantFilter - cmdParams = @{ - Identity = $RuleName - } - useSystemMailbox = $true - } - - switch ($State) { - 'Enable' { - $ExoRequestParam.Add('cmdlet', 'Enable-MalwareFilterRule') - } - 'Disable' { - $ExoRequestParam.Add('cmdlet', 'Disable-MalwareFilterRule') - } - Default { - throw 'Invalid state' - } - } - $null = New-ExoRequest @ExoRequestParam - - $Result = "Successfully set Malware Filter rule $($RuleName) to $($State)" - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev Info - $StatusCode = [HttpStatusCode]::OK - } catch { - $ErrorMessage = Get-CippException -Exception $_ - $Result = "Failed setting Malware Filter rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage - $StatusCode = [HttpStatusCode]::InternalServerError - } - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $StatusCode - Body = @{Results = $Result } - }) -} +function Invoke-EditMalwareFilter { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.SpamFilter.Read + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $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. + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName + $State = $Request.Query.State ?? $Request.Body.State + + try { + $ExoRequestParam = @{ + tenantid = $TenantFilter + cmdParams = @{ + Identity = $RuleName + } + useSystemMailbox = $true + } + + switch ($State) { + 'Enable' { + $ExoRequestParam.Add('cmdlet', 'Enable-MalwareFilterRule') + } + 'Disable' { + $ExoRequestParam.Add('cmdlet', 'Disable-MalwareFilterRule') + } + Default { + throw 'Invalid state' + } + } + $null = New-ExoRequest @ExoRequestParam + + $Result = "Successfully set Malware Filter rule $($RuleName) to $($State)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev Info + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed setting Malware Filter rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError + } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @{Results = $Result } + }) +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeAttachmentsFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeAttachmentsFilter.ps1 index 1adb00b34010..a6eae5585946 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeAttachmentsFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeAttachmentsFilter.ps1 @@ -1,57 +1,57 @@ -function Invoke-EditSafeAttachmentsFilter { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.SpamFilter.Read - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - $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. - $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter - $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName - $State = $Request.Query.State ?? $Request.Body.State - - try { - $ExoRequestParam = @{ - tenantid = $TenantFilter - cmdParams = @{ - Identity = $RuleName - } - useSystemMailbox = $true - } - - switch ($State) { - 'Enable' { - $ExoRequestParam.Add('cmdlet', 'Enable-SafeAttachmentRule') - } - 'Disable' { - $ExoRequestParam.Add('cmdlet', 'Disable-SafeAttachmentRule') - } - Default { - throw 'Invalid state' - } - } - $null = New-ExoRequest @ExoRequestParam - - $Result = "Successfully set SafeAttachment rule $($RuleName) to $($State)" - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Info' - $StatusCode = [HttpStatusCode]::OK - } catch { - $ErrorMessage = Get-CippException -Exception $_ - $Result = "Failed setting SafeAttachment rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage - $StatusCode = [HttpStatusCode]::InternalServerError - } - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $StatusCode - Body = @{Results = $Result } - }) -} +function Invoke-EditSafeAttachmentsFilter { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.SpamFilter.Read + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $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. + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName + $State = $Request.Query.State ?? $Request.Body.State + + try { + $ExoRequestParam = @{ + tenantid = $TenantFilter + cmdParams = @{ + Identity = $RuleName + } + useSystemMailbox = $true + } + + switch ($State) { + 'Enable' { + $ExoRequestParam.Add('cmdlet', 'Enable-SafeAttachmentRule') + } + 'Disable' { + $ExoRequestParam.Add('cmdlet', 'Disable-SafeAttachmentRule') + } + Default { + throw 'Invalid state' + } + } + $null = New-ExoRequest @ExoRequestParam + + $Result = "Successfully set SafeAttachment rule $($RuleName) to $($State)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Info' + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed setting SafeAttachment rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError + } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @{Results = $Result } + }) +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeLinksFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeLinksFilter.ps1 index fd7b11144b48..89141c9f413e 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeLinksFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Invoke-EditSafeLinksFilter.ps1 @@ -1,57 +1,57 @@ -function Invoke-EditSafeLinksFilter { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Exchange.SpamFilter.Read - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - $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. - $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter - $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName - $State = $Request.Query.State ?? $Request.Body.State - - try { - $ExoRequestParam = @{ - tenantid = $TenantFilter - cmdParams = @{ - Identity = $RuleName - } - useSystemMailbox = $true - } - - switch ($State) { - 'Enable' { - $ExoRequestParam.Add('cmdlet', 'Enable-SafeLinksRule') - } - 'Disable' { - $ExoRequestParam.Add('cmdlet', 'Disable-SafeLinksRule') - } - Default { - throw 'Invalid state' - } - } - $null = New-ExoRequest @ExoRequestParam - - $Result = "Successfully set SafeLinks rule $($RuleName) to $($State)" - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev Info - $StatusCode = [HttpStatusCode]::OK - } catch { - $ErrorMessage = Get-CippException -Exception $_ - $Result = "Failed setting SafeLinks rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" - Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' - $StatusCode = [HttpStatusCode]::InternalServerError - } - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $StatusCode - Body = @{Results = $Result } - }) -} +function Invoke-EditSafeLinksFilter { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.SpamFilter.Read + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $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. + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $RuleName = $Request.Query.RuleName ?? $Request.Body.RuleName + $State = $Request.Query.State ?? $Request.Body.State + + try { + $ExoRequestParam = @{ + tenantid = $TenantFilter + cmdParams = @{ + Identity = $RuleName + } + useSystemMailbox = $true + } + + switch ($State) { + 'Enable' { + $ExoRequestParam.Add('cmdlet', 'Enable-SafeLinksRule') + } + 'Disable' { + $ExoRequestParam.Add('cmdlet', 'Disable-SafeLinksRule') + } + Default { + throw 'Invalid state' + } + } + $null = New-ExoRequest @ExoRequestParam + + $Result = "Successfully set SafeLinks rule $($RuleName) to $($State)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev Info + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed setting SafeLinks rule $($RuleName) to $($State). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -Sev 'Error' + $StatusCode = [HttpStatusCode]::InternalServerError + } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @{Results = $Result } + }) +} From 95de2b1b96f8016d844544851b965406bc37cd5f Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 19:26:34 +0100 Subject: [PATCH 138/167] updated clean cache removal --- .../Webhooks/Test-CIPPAuditLogRules.ps1 | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 index 8c6bb9b79a1d..361220d65126 100644 --- a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 @@ -166,6 +166,20 @@ function Test-CIPPAuditLogRules { $RecordEndTime = Get-Date $RecordSeconds = ($RecordEndTime - $RecordStartTime).TotalSeconds Write-Warning "Task took $RecordSeconds seconds for RowKey $($AuditRecord.id)" + Write-Host "Removing row $($AuditRecord.id) from cache" + $RowEntity = Get-CIPPAzDataTableEntity @CacheWebhooksTable -Filter "PartitionKey eq '$TenantFilter' and RowKey eq '$($Row.id)'" + try { + Write-Information 'Removing processed rows from cache' + if ($AuditRecord.id) { + $RowEntity = Get-CIPPAzDataTableEntity @CacheWebhooksTable -Filter "PartitionKey eq '$TenantFilter' and RowKey eq '$($AuditRecord.id)'" + if ($RowEntity) { + Remove-AzDataTableEntity @CacheWebhooksTable -Entity $RowEntity -Force + Write-Information "Removed row $($AuditRecord.id) from cache" + } + } + } catch { + Write-Information "Error removing rows from cache: $($_.Exception.Message)" + } } #write-warning "Processed Data: $(($ProcessedData | Measure-Object).Count) - This should be higher than 0 in many cases, because the where object has not run yet." #write-warning "Creating filters - $(($ProcessedData.operation | Sort-Object -Unique) -join ',') - $($TenantFilter)" @@ -239,21 +253,5 @@ function Test-CIPPAuditLogRules { } } - # Remove processed rows from the cache table - try { - Write-Information 'Removing processed rows from cache' - foreach ($Row in $Rows) { - if ($Row.id) { - $RowEntity = Get-CIPPAzDataTableEntity @CacheWebhooksTable -Filter "PartitionKey eq '$TenantFilter' and RowKey eq '$($Row.id)'" - if ($RowEntity) { - Remove-AzDataTableEntity @CacheWebhooksTable -Entity $RowEntity -Force - Write-Information "Removed row $($Row.id) from cache" - } - } - } - } catch { - Write-Information "Error removing rows from cache: $($_.Exception.Message)" - } - return $Results } From 0b08f616232cbe0e8d7e76cfbe61c0def1ce7f7b Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 3 Mar 2025 14:34:28 -0500 Subject: [PATCH 139/167] clean up logging --- host.json | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/host.json b/host.json index ae174a8b41b8..4e9888399363 100644 --- a/host.json +++ b/host.json @@ -13,19 +13,5 @@ "maxConcurrentActivityFunctions": 1, "maxConcurrentOrchestratorFunctions": 1 } - }, - "logging": { - "logLevel": { - "default": "Trace", - "Host.Results": "Trace", - "Host.Aggregator": "Trace", - "Function": "Trace", - "Host.Executor": "Trace" - }, - "applicationInsights": { - "samplingSettings": { - "isEnabled": false - } - } } } From 9dd5154e9321d81a0a44b501dafe64b1b0a7cc9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 3 Mar 2025 20:39:25 +0100 Subject: [PATCH 140/167] fix: add disable forwarding option in offboarding job --- .../Administration/Users/Invoke-CIPPOffboardingJob.ps1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-CIPPOffboardingJob.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-CIPPOffboardingJob.ps1 index 029c2c11c4cb..3bb2fc720957 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-CIPPOffboardingJob.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-CIPPOffboardingJob.ps1 @@ -52,6 +52,9 @@ function Invoke-CIPPOffboardingJob { Set-CIPPForwarding -userid $userid -username $username -tenantFilter $TenantFilter -Forward $Options.forward.value -KeepCopy $KeepCopy -Headers $Headers -APIName $APIName } } + { $_.disableForwarding } { + Set-CIPPForwarding -userid $userid -username $username -tenantFilter $TenantFilter -Disable $true -Headers $Headers -APIName $APIName + } { $_.RemoveLicenses -eq $true } { Remove-CIPPLicense -userid $userid -username $Username -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName -Schedule } From 160e262d6ef2af4c5c2ac507413dc1e0f2a25f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Mon, 3 Mar 2025 20:48:49 +0100 Subject: [PATCH 141/167] Fix merge conflict --- .../Administration/Invoke-ExecEnableArchive.ps1 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEnableArchive.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEnableArchive.ps1 index fe7b1811a419..bfb8cc74ad62 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEnableArchive.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEnableArchive.ps1 @@ -11,14 +11,16 @@ Function Invoke-ExecEnableArchive { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' + $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. $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter $ID = $Request.Query.id ?? $Request.Body.id + $UserName = $Request.Query.username ?? $Request.Body.username Try { - $ResultsArch = Set-CIPPMailboxArchive -userid $ID -tenantFilter $TenantFilter -APIName $APINAME -Headers $Request.Headers -ArchiveEnabled $true + $ResultsArch = Set-CIPPMailboxArchive -userid $ID -tenantFilter $TenantFilter -APIName $APIName -Headers $Headers -ArchiveEnabled $true -Username $UserName if ($ResultsArch -like 'Failed to set archive*') { throw $ResultsArch } $StatusCode = [HttpStatusCode]::OK } catch { From 49f40729a15be874beefebaf2859796b18f9b4ca Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 3 Mar 2025 16:59:40 -0500 Subject: [PATCH 142/167] fix: defender policy error when no policy exists --- .../MEM/Invoke-AddDefenderDeployment.ps1 | 80 +++++++++++-------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddDefenderDeployment.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddDefenderDeployment.ps1 index 95de673985c4..b355013cdb96 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddDefenderDeployment.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-AddDefenderDeployment.ps1 @@ -14,7 +14,7 @@ Function Invoke-AddDefenderDeployment { Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' $Tenants = ($Request.body.selectedTenants).value - if ('AllTenants' -in $Tenants) { $Tenants = (Get-Tenants).defaultDomainName } + if ('AllTenants' -in $Tenants) { $Tenants = (Get-Tenants -IncludeErrors).defaultDomainName } $Compliance = $request.body.Compliance $PolicySettings = $request.body.Policy $ASR = $request.body.ASR @@ -35,7 +35,12 @@ Function Invoke-AddDefenderDeployment { iosMobileApplicationManagementEnabled = [bool]$Compliance.appSync microsoftDefenderForEndpointAttachEnabled = [bool]$true } | ConvertTo-Json -Compress - $ExistingSettings = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/mobileThreatDefenseConnectors/fc780465-2017-40d4-a0c5-307022471b92' -tenantid $tenant + try { + $ExistingSettings = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/mobileThreatDefenseConnectors/fc780465-2017-40d4-a0c5-307022471b92' -tenantid $tenant + } catch { + $ExistingSettings = $false + } + if ($ExistingSettings) { "Defender Intune Configuration already active for $($Tenant). Skipping" } else { @@ -81,9 +86,9 @@ Function Invoke-AddDefenderDeployment { @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' ; settingInstance = @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' ; settingDefinitionId = 'device_vendor_msft_policy_config_defender_enablelowcpupriority' ; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_enablelowcpupriority_1' ; settingValueTemplateReference = @{settingValueTemplateId = '045a4a13-deee-4e24-9fe4-985c9357680d' } } ; settingInstanceTemplateReference = @{settingInstanceTemplateId = 'cdeb96cf-18f5-4477-a710-0ea9ecc618af' } } } } } - $CheckExististing = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies' -tenantid $tenant - Write-Host ($CheckExististing | ConvertTo-Json) - if ('Default AV Policy' -in $CheckExististing.Name) { + $CheckExisting = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies' -tenantid $tenant + Write-Host ($CheckExisting | ConvertTo-Json) + if ('Default AV Policy' -in $CheckExisting.Name) { "$($Tenant): AV Policy already exists. Skipping" } else { $PolBody = ConvertTo-Json -Depth 10 -Compress -InputObject @{ @@ -93,8 +98,11 @@ Function Invoke-AddDefenderDeployment { technologies = 'mdm,microsoftSense' roleScopeTagIds = @('0') templateReference = @{templateId = '804339ad-1553-4478-a742-138fb5807418_1' } - settings = $Settings + settings = @($Settings) } + + Write-Information ($PolBody) + $PolicyRequest = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies' -tenantid $tenant -type POST -body $PolBody if ($PolicySettings.AssignTo -ne 'None') { $AssignBody = if ($PolicySettings.AssignTo -ne 'AllDevicesAndUsers') { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.' + $($PolicySettings.AssignTo) + 'AssignmentTarget"}}]}' } else { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}},{"id":"","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"}}]}' } @@ -123,8 +131,6 @@ Function Invoke-AddDefenderDeployment { { $_.BlockUnsignedDrivers } { @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance'; settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockabuseofexploitedvulnerablesigneddrivers'; choiceSettingValue = @{'@odata.type' = '#microsoft.graph.deviceManagementConfigurationchoiceSettingValue'; value = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_blockabuseofexploitedvulnerablesigneddrivers_block' } } } } - - $ASRbody = ConvertTo-Json -Depth 15 -Compress -InputObject @{ name = 'ASR Default rules' description = '' @@ -147,14 +153,16 @@ Function Invoke-AddDefenderDeployment { "$($Tenant): ASR Policy already exists. Skipping" } else { Write-Host $ASRbody - $ASRRequest = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies' -tenantid $tenant -type POST -body $ASRbody - Write-Host ($ASRRequest.id) - if ($ASR.AssignTo -ne 'none') { - $AssignBody = if ($ASR.AssignTo -ne 'AllDevicesAndUsers') { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.' + $($asr.AssignTo) + 'AssignmentTarget"}}]}' } else { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}},{"id":"","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"}}]}' } - $assign = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($ASRRequest.id)')/assign" -tenantid $tenant -type POST -body $AssignBody - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($Tenant) -message "Assigned policy $($Displayname) to $($ASR.AssignTo)" -Sev 'Info' + if (($ASRSettings | Measure-Object).Count -gt 0) { + $ASRRequest = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies' -tenantid $tenant -type POST -body $ASRbody + Write-Host ($ASRRequest.id) + if ($ASR.AssignTo -and $ASR.AssignTo -ne 'none') { + $AssignBody = if ($ASR.AssignTo -ne 'AllDevicesAndUsers') { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.' + $($asr.AssignTo) + 'AssignmentTarget"}}]}' } else { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}},{"id":"","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"}}]}' } + $assign = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($ASRRequest.id)')/assign" -tenantid $tenant -type POST -body $AssignBody + Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($Tenant) -message "Assigned policy $($Displayname) to $($ASR.AssignTo)" -Sev 'Info' + } + "$($Tenant): Successfully added ASR Settings" } - "$($Tenant): Successfully added ASR Settings" } } if ($EDR) { @@ -209,27 +217,29 @@ Function Invoke-AddDefenderDeployment { } } - $EDRbody = ConvertTo-Json -Depth 15 -Compress -InputObject @{ - name = 'EDR Configuration' - description = '' - platforms = 'windows10' - technologies = 'mdm,microsoftSense' - roleScopeTagIds = @('0') - templateReference = @{templateId = '0385b795-0f2f-44ac-8602-9f65bf6adede_1' } - settings = @($EDRSettings) - } - Write-Host ( $EDRbody) - $CheckExististingEDR = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies' -tenantid $tenant | Where-Object -Property Name -EQ 'EDR Configuration' - if ('EDR Configuration' -in $CheckExististingEDR.Name) { - "$($Tenant): EDR Policy already exists. Skipping" - } else { - $EDRRequest = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies' -tenantid $tenant -type POST -body $EDRbody - if ($ASR.AssignTo -ne 'none') { - $AssignBody = if ($ASR.AssignTo -ne 'AllDevicesAndUsers') { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.' + $($asr.AssignTo) + 'AssignmentTarget"}}]}' } else { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}},{"id":"","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"}}]}' } - $assign = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($EDRRequest.id)')/assign" -tenantid $tenant -type POST -body $AssignBody - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($Tenant) -message "Assigned EDR policy $($Displayname) to $($ASR.AssignTo)" -Sev 'Info' + if (($EDRSettings | Measure-Object).Count -gt 0) { + $EDRbody = ConvertTo-Json -Depth 15 -Compress -InputObject @{ + name = 'EDR Configuration' + description = '' + platforms = 'windows10' + technologies = 'mdm,microsoftSense' + roleScopeTagIds = @('0') + templateReference = @{templateId = '0385b795-0f2f-44ac-8602-9f65bf6adede_1' } + settings = @($EDRSettings) + } + Write-Host ( $EDRbody) + $CheckExististingEDR = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies' -tenantid $tenant | Where-Object -Property Name -EQ 'EDR Configuration' + if ('EDR Configuration' -in $CheckExististingEDR.Name) { + "$($Tenant): EDR Policy already exists. Skipping" + } else { + $EDRRequest = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies' -tenantid $tenant -type POST -body $EDRbody + if ($ASR -and $ASR.AssignTo -ne 'none') { + $AssignBody = if ($ASR.AssignTo -ne 'AllDevicesAndUsers') { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.' + $($asr.AssignTo) + 'AssignmentTarget"}}]}' } else { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}},{"id":"","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"}}]}' } + $assign = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($EDRRequest.id)')/assign" -tenantid $tenant -type POST -body $AssignBody + Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($Tenant) -message "Assigned EDR policy $($Displayname) to $($ASR.AssignTo)" -Sev 'Info' + } + "$($Tenant): Successfully added EDR Settings" } - "$($Tenant): Successfully added EDR Settings" } } } catch { From 56743818134540325d35b077108b2177ccba26fe Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 23:03:02 +0100 Subject: [PATCH 143/167] fix delete typo --- .../Orchestrator Functions/Start-AuditLogOrchestrator.ps1 | 2 +- Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 index a0c30e7133bc..f3827f2e9b48 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 @@ -53,7 +53,7 @@ function Start-AuditLogOrchestrator { } if ($ProcessBatch.Count -gt 0) { $ProcessInputObject = [PSCustomObject]@{ - OrchestratorName = 'AuditLogsProcess' + OrchestratorName = 'AuditLogTenantProcess' Batch = @($ProcessBatch) SkipLog = $true } diff --git a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 index 361220d65126..f2ad39f9f4ce 100644 --- a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 @@ -167,7 +167,7 @@ function Test-CIPPAuditLogRules { $RecordSeconds = ($RecordEndTime - $RecordStartTime).TotalSeconds Write-Warning "Task took $RecordSeconds seconds for RowKey $($AuditRecord.id)" Write-Host "Removing row $($AuditRecord.id) from cache" - $RowEntity = Get-CIPPAzDataTableEntity @CacheWebhooksTable -Filter "PartitionKey eq '$TenantFilter' and RowKey eq '$($Row.id)'" + $RowEntity = Get-CIPPAzDataTableEntity @CacheWebhooksTable -Filter "PartitionKey eq '$TenantFilter' and RowKey eq '$($AuditRecord.id)'" try { Write-Information 'Removing processed rows from cache' if ($AuditRecord.id) { From 0cc8dacebb1adc854a314942f60763d29719698a Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 23:09:25 +0100 Subject: [PATCH 144/167] remove redunant line, bring back logging for a bit, sorry bobby --- .../Public/Webhooks/Test-CIPPAuditLogRules.ps1 | 1 - host.json | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 index f2ad39f9f4ce..2623f399ca84 100644 --- a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 @@ -167,7 +167,6 @@ function Test-CIPPAuditLogRules { $RecordSeconds = ($RecordEndTime - $RecordStartTime).TotalSeconds Write-Warning "Task took $RecordSeconds seconds for RowKey $($AuditRecord.id)" Write-Host "Removing row $($AuditRecord.id) from cache" - $RowEntity = Get-CIPPAzDataTableEntity @CacheWebhooksTable -Filter "PartitionKey eq '$TenantFilter' and RowKey eq '$($AuditRecord.id)'" try { Write-Information 'Removing processed rows from cache' if ($AuditRecord.id) { diff --git a/host.json b/host.json index 4e9888399363..ae174a8b41b8 100644 --- a/host.json +++ b/host.json @@ -13,5 +13,19 @@ "maxConcurrentActivityFunctions": 1, "maxConcurrentOrchestratorFunctions": 1 } + }, + "logging": { + "logLevel": { + "default": "Trace", + "Host.Results": "Trace", + "Host.Aggregator": "Trace", + "Function": "Trace", + "Host.Executor": "Trace" + }, + "applicationInsights": { + "samplingSettings": { + "isEnabled": false + } + } } } From 86e1e1da3cc805335981938d0105b60fd61e2552 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 23:31:09 +0100 Subject: [PATCH 145/167] extra logging --- .../Orchestrator Functions/Start-AuditLogOrchestrator.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 index f3827f2e9b48..cd43c9209ab4 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 @@ -36,6 +36,7 @@ function Start-AuditLogOrchestrator { if ($TenantGroups.Count -gt 0) { Write-Information "Processing webhook cache for $($TenantGroups.Count) tenants" + Write-Warning "AuditLogJobs are: $($TenantGroups.Count) tenants. Tenants: $($tenantgroups.name | ConvertTo-Json) " $ProcessQueue = New-CippQueueEntry -Name 'Audit Logs Process' -Reference 'AuditLogsProcess' -TotalTasks ($TenantGroups | Measure-Object -Property Count -Sum).Sum $ProcessBatch = foreach ($TenantGroup in $TenantGroups) { $TenantFilter = $TenantGroup.Name From b93ac04041cb851c3afb871b7a5044db8a8196bf Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 23:33:31 +0100 Subject: [PATCH 146/167] lots of logging --- .../Orchestrator Functions/Start-AuditLogOrchestrator.ps1 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 index cd43c9209ab4..813392d2d3b4 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 @@ -34,9 +34,10 @@ function Start-AuditLogOrchestrator { $WebhookCache = Get-CIPPAzDataTableEntity @WebhookCacheTable $TenantGroups = $WebhookCache | Group-Object -Property PartitionKey - if ($TenantGroups.Count -gt 0) { + if ($TenantGroups) { Write-Information "Processing webhook cache for $($TenantGroups.Count) tenants" - Write-Warning "AuditLogJobs are: $($TenantGroups.Count) tenants. Tenants: $($tenantgroups.name | ConvertTo-Json) " + Write-Warning "AuditLogJobs are: $($TenantGroups.Count) tenants. Tenants: $($TenantGroups.name | ConvertTo-Json -Compress) " + Write-Warning "Here are the groups: $($TenantGroups | ConvertTo-Json -Compress)" $ProcessQueue = New-CippQueueEntry -Name 'Audit Logs Process' -Reference 'AuditLogsProcess' -TotalTasks ($TenantGroups | Measure-Object -Property Count -Sum).Sum $ProcessBatch = foreach ($TenantGroup in $TenantGroups) { $TenantFilter = $TenantGroup.Name From 66d0d8cf6a37f98a4202f3685ba6615dc33eb9d0 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Mon, 3 Mar 2025 23:34:47 +0100 Subject: [PATCH 147/167] .count doesnt exist on single objects. --- .../Orchestrator Functions/Start-AuditLogOrchestrator.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 index 813392d2d3b4..72441b832ccd 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 @@ -53,7 +53,7 @@ function Start-AuditLogOrchestrator { } } } - if ($ProcessBatch.Count -gt 0) { + if ($ProcessBatch) { $ProcessInputObject = [PSCustomObject]@{ OrchestratorName = 'AuditLogTenantProcess' Batch = @($ProcessBatch) From 5f899fb1908f6fbc71ebc19f23b4ac1ccdc42b76 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 3 Mar 2025 18:09:40 -0500 Subject: [PATCH 148/167] feat: trigger automatic permission check after 4 hours --- .../CIPP/Settings/Invoke-ExecAccessChecks.ps1 | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecAccessChecks.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecAccessChecks.ps1 index 8df5f7fe9c37..5a403a6894f9 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecAccessChecks.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecAccessChecks.ps1 @@ -15,11 +15,15 @@ Function Invoke-ExecAccessChecks { $Table = Get-CIPPTable -tablename 'AccessChecks' $LastRun = (Get-Date).ToUniversalTime() + $4HoursAgo = (Get-Date).AddHours(-1).ToUniversalTime() + $TimestampFilter = $4HoursAgo.ToString('yyyy-MM-ddTHH:mm:ss.fffK') + + switch ($Request.Query.Type) { 'Permissions' { if ($Request.Query.SkipCache -ne 'true' -or $Request.Query.SkipCache -ne $true) { try { - $Cache = Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq 'AccessPermissions'" + $Cache = Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq 'AccessPermissions' and Timestamp and Timestamp ge datetime'$TimestampFilter'" $Results = $Cache.Data | ConvertFrom-Json } catch { $Results = $null @@ -85,7 +89,7 @@ Function Invoke-ExecAccessChecks { } } - if ($Request.Query.SkipCache -eq 'true' -or $Request.Query.SkipCache -eq $true) { + if ($Request.Query.SkipCache -eq 'true' -or $Request.Query.SkipCache -eq $true -or $LastRun -lt $4HoursAgo) { $Message = Test-CIPPAccessTenant -Headers $Request.Headers } @@ -99,7 +103,7 @@ Function Invoke-ExecAccessChecks { 'GDAP' { if (!$Request.Query.SkipCache -eq 'true' -or !$Request.Query.SkipCache -eq $true) { try { - $Cache = Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq 'GDAPRelationships'" + $Cache = Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq 'GDAPRelationships' and Timestamp ge datetime'$TimestampFilter'" $Results = $Cache.Data | ConvertFrom-Json } catch { $Results = $null From b5014c2c8646269da630b2138c3d03af48fe29ca Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 3 Mar 2025 18:11:26 -0500 Subject: [PATCH 149/167] fix: add more logging to mfa report --- Modules/CIPPCore/Public/Get-CIPPMFAState.ps1 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/CIPPCore/Public/Get-CIPPMFAState.ps1 b/Modules/CIPPCore/Public/Get-CIPPMFAState.ps1 index 68b9e03ae1a3..d27f3fd0f820 100644 --- a/Modules/CIPPCore/Public/Get-CIPPMFAState.ps1 +++ b/Modules/CIPPCore/Public/Get-CIPPMFAState.ps1 @@ -17,10 +17,12 @@ function Get-CIPPMFAState { } } + $Errors = [System.Collections.Generic.List[object]]::new() try { $SecureDefaultsState = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/identitySecurityDefaultsEnforcementPolicy' -tenantid $TenantFilter ).IsEnabled } catch { Write-Host "Secure Defaults not available: $($_.Exception.Message)" + $Errors.Add(@{Step = 'SecureDefaults'; Message = $_.Exception.Message }) } $CAState = [System.Collections.Generic.List[object]]::new() @@ -29,6 +31,7 @@ function Get-CIPPMFAState { } catch { $CAState.Add('Not Licensed for Conditional Access') | Out-Null $MFARegistration = $null + $Errors.Add(@{Step = 'MFARegistration'; Message = $_.Exception.Message }) Write-Host "User registration details not available: $($_.Exception.Message)" } @@ -58,6 +61,7 @@ function Get-CIPPMFAState { } catch { $CASuccess = $false $CAError = "CA policies not available: $($_.Exception.Message)" + $Errors.Add(@{Step = 'CAPolicies'; Message = $_.Exception.Message }) } } @@ -110,6 +114,7 @@ function Get-CIPPMFAState { CoveredByCA = $CoveredByCA CAPolicies = $UserCAState CoveredBySD = $SecureDefaultsState + Errors = $Errors RowKey = [string]($_.UserPrincipalName).replace('#', '') PartitionKey = 'users' } From 91a20c9d104d93ef01b2285a1df7a042d2288526 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 4 Mar 2025 01:37:31 +0100 Subject: [PATCH 150/167] commentt logs --- .../Orchestrator Functions/Start-AuditLogOrchestrator.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 index 72441b832ccd..41a3053893db 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 @@ -36,8 +36,8 @@ function Start-AuditLogOrchestrator { if ($TenantGroups) { Write-Information "Processing webhook cache for $($TenantGroups.Count) tenants" - Write-Warning "AuditLogJobs are: $($TenantGroups.Count) tenants. Tenants: $($TenantGroups.name | ConvertTo-Json -Compress) " - Write-Warning "Here are the groups: $($TenantGroups | ConvertTo-Json -Compress)" + #Write-Warning "AuditLogJobs are: $($TenantGroups.Count) tenants. Tenants: $($TenantGroups.name | ConvertTo-Json -Compress) " + #Write-Warning "Here are the groups: $($TenantGroups | ConvertTo-Json -Compress)" $ProcessQueue = New-CippQueueEntry -Name 'Audit Logs Process' -Reference 'AuditLogsProcess' -TotalTasks ($TenantGroups | Measure-Object -Property Count -Sum).Sum $ProcessBatch = foreach ($TenantGroup in $TenantGroups) { $TenantFilter = $TenantGroup.Name From 280556aa8b7e6ff43712a2cb785f4a5c4c2e0a76 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 4 Mar 2025 01:37:49 +0100 Subject: [PATCH 151/167] hostt rollback --- host.json | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/host.json b/host.json index ae174a8b41b8..4e9888399363 100644 --- a/host.json +++ b/host.json @@ -13,19 +13,5 @@ "maxConcurrentActivityFunctions": 1, "maxConcurrentOrchestratorFunctions": 1 } - }, - "logging": { - "logLevel": { - "default": "Trace", - "Host.Results": "Trace", - "Host.Aggregator": "Trace", - "Function": "Trace", - "Host.Executor": "Trace" - }, - "applicationInsights": { - "samplingSettings": { - "isEnabled": false - } - } } } From d7ef4c44469ccc82675fdaaf23c339f0ea265f53 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 3 Mar 2025 20:02:46 -0500 Subject: [PATCH 152/167] add logging instead of error object --- Modules/CIPPCore/Public/Get-CIPPMFAState.ps1 | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Modules/CIPPCore/Public/Get-CIPPMFAState.ps1 b/Modules/CIPPCore/Public/Get-CIPPMFAState.ps1 index d27f3fd0f820..77a9af81e609 100644 --- a/Modules/CIPPCore/Public/Get-CIPPMFAState.ps1 +++ b/Modules/CIPPCore/Public/Get-CIPPMFAState.ps1 @@ -31,7 +31,9 @@ function Get-CIPPMFAState { } catch { $CAState.Add('Not Licensed for Conditional Access') | Out-Null $MFARegistration = $null - $Errors.Add(@{Step = 'MFARegistration'; Message = $_.Exception.Message }) + if ($_.Exception.Message -ne "Tenant is not a B2C tenant and doesn't have premium licenses") { + $Errors.Add(@{Step = 'MFARegistration'; Message = $_.Exception.Message }) + } Write-Host "User registration details not available: $($_.Exception.Message)" } @@ -114,11 +116,18 @@ function Get-CIPPMFAState { CoveredByCA = $CoveredByCA CAPolicies = $UserCAState CoveredBySD = $SecureDefaultsState - Errors = $Errors RowKey = [string]($_.UserPrincipalName).replace('#', '') PartitionKey = 'users' } - + } + $ErrorCount = ($Errors | Measure-Object).Count + if ($ErrorCount -gt 0) { + if ($ErrorCount -gt 1) { + $Text = 'errors' + } else { + $Text = 'an error' + } + Write-LogMessage -headers $Headers -API $APIName -Tenant $TenantFilter -message "The MFA report encountered $Text, see log data for details." -Sev 'Error' -LogData @($Errors.Message) } return $GraphRequest } From cb246ac4f0b28c317aed49629c4c411b7172f487 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 3 Mar 2025 20:20:30 -0500 Subject: [PATCH 153/167] fix casing --- Config/CyberEssentials.BPATemplate.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config/CyberEssentials.BPATemplate.json b/Config/CyberEssentials.BPATemplate.json index 31d25321dc88..5d340abd2a11 100644 --- a/Config/CyberEssentials.BPATemplate.json +++ b/Config/CyberEssentials.BPATemplate.json @@ -54,7 +54,7 @@ "StoreAs": "JSON", "API": "Graph", "ExtractFields": ["windowsProtectionState"], - "parameters": {}, + "Parameters": {}, "URL": "https://graph.microsoft.com/beta/deviceManagement/managedDevices?$expand=windowsProtectionState" }, { From 2051e7c92f2c6c013a81c185f790f69bd16a55c9 Mon Sep 17 00:00:00 2001 From: Esco Date: Tue, 4 Mar 2025 12:30:00 +0100 Subject: [PATCH 154/167] feat: added set sponsor in edit user --- .../Identity/Administration/Users/Invoke-EditUser.ps1 | 8 ++++++++ Modules/CIPPCore/Public/New-CIPPUserTask.ps1 | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) 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 31f09b0df2ae..a7fa34715afb 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 @@ -181,6 +181,14 @@ Function Invoke-EditUser { $null = $results.Add("Success. Set $($UserObj.DisplayName)'s manager to $($Request.body.setManager.label)") } + if ($Request.body.setSponsor.value) { + $SponsorBody = [PSCustomObject]@{'@odata.id' = "https://graph.microsoft.com/beta/users/$($Request.body.setSponsor.value)" } + $SponsorBodyJSON = ConvertTo-Json -Compress -Depth 10 -InputObject $SponsorBody + $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($UserObj.id)/sponsors/`$ref" -tenantid $UserObj.tenantFilter -type POST -body $SponsorBodyJSON -Verbose + Write-LogMessage -headers $Request.Headers -API $ApiName -tenant $UserObj.tenantFilter -message "Set $($UserObj.DisplayName)'s sponsor to $($Request.body.setSponsor.label)" -Sev Info + $null = $results.Add("Success. Set $($UserObj.DisplayName)'s sponsor to $($Request.body.setSponsor.label)") + } + if ($RemoveFromGroups) { $RemoveFromGroups | ForEach-Object { diff --git a/Modules/CIPPCore/Public/New-CIPPUserTask.ps1 b/Modules/CIPPCore/Public/New-CIPPUserTask.ps1 index d23a10deb209..f0738334ee7d 100644 --- a/Modules/CIPPCore/Public/New-CIPPUserTask.ps1 +++ b/Modules/CIPPCore/Public/New-CIPPUserTask.ps1 @@ -49,6 +49,11 @@ function New-CIPPUserTask { $results.add($ManagerResult) } + if ($userobj.setSponsor) { + $SponsorResult = Set-CIPPManager -user $CreationResults.username -Manager $userObj.setSponsor.value -TenantFilter $UserObj.tenantFilter -APIName 'Set Sponsor' -Headers $Headers + $results.add($SponsorResult) + } + return @{ Results = $results username = $CreationResults.username @@ -56,4 +61,3 @@ function New-CIPPUserTask { CopyFrom = $CopyFrom } } - From 1bf89c9ff68496476311365ef9ff1aaf3e00d79e Mon Sep 17 00:00:00 2001 From: Esco Date: Tue, 4 Mar 2025 14:49:14 +0100 Subject: [PATCH 155/167] feat: display manager in view user --- .../Identity/Administration/Users/Invoke-ListUsers.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUsers.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUsers.ps1 index 91dfb2187187..a132268e8390 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUsers.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUsers.ps1 @@ -20,7 +20,7 @@ Function Invoke-ListUsers { $userid = $Request.Query.UserID $GraphRequest = if ($TenantFilter -ne 'AllTenants') { - New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($userid)?`$top=999&`$filter=$GraphFilter&`$count=true" -tenantid $TenantFilter -ComplexFilter | ForEach-Object { + New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($userid)?`$top=999&`$filter=$GraphFilter&`$count=true&`$expand=manager(`$select=id,userPrincipalName,displayName)" -tenantid $TenantFilter -ComplexFilter | ForEach-Object { $_ | Add-Member -MemberType NoteProperty -Name 'onPremisesSyncEnabled' -Value ([bool]($_.onPremisesSyncEnabled)) -Force $_ | Add-Member -MemberType NoteProperty -Name 'username' -Value ($_.userPrincipalName -split '@' | Select-Object -First 1) -Force $_ | Add-Member -MemberType NoteProperty -Name 'Aliases' -Value ($_.ProxyAddresses -join ', ') -Force From 39248bf1593eca0fa71b95e0947d5a8a411f317d Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 4 Mar 2025 09:41:20 -0500 Subject: [PATCH 156/167] feat: add application roles to permission check --- .../GraphHelper/Read-JwtAccessDetails.ps1 | 4 +++- .../Public/Test-CIPPAccessPermissions.ps1 | 18 +++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Modules/CIPPCore/Public/GraphHelper/Read-JwtAccessDetails.ps1 b/Modules/CIPPCore/Public/GraphHelper/Read-JwtAccessDetails.ps1 index ced968960b4b..58cb338240bc 100644 --- a/Modules/CIPPCore/Public/GraphHelper/Read-JwtAccessDetails.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/Read-JwtAccessDetails.ps1 @@ -18,6 +18,7 @@ function Read-JwtAccessDetails { IPAddress = '' Name = '' Scope = '' + Roles = '' TenantId = '' UserPrincipalName = '' } @@ -43,8 +44,9 @@ function Read-JwtAccessDetails { $TokenDetails.IPAddress = $TokenObj.ipaddr $TokenDetails.Name = $TokenObj.name $TokenDetails.Scope = $TokenObj.scp -split ' ' + $TokenDetails.Roles = $TokenObj.roles $TokenDetails.TenantId = $TokenObj.tid $TokenDetails.UserPrincipalName = $TokenObj.upn return $TokenDetails -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Test-CIPPAccessPermissions.ps1 b/Modules/CIPPCore/Public/Test-CIPPAccessPermissions.ps1 index e111bbf55d2e..7fbc388cbbec 100644 --- a/Modules/CIPPCore/Public/Test-CIPPAccessPermissions.ps1 +++ b/Modules/CIPPCore/Public/Test-CIPPAccessPermissions.ps1 @@ -128,6 +128,9 @@ function Test-CIPPAccessPermissions { $Messages.Add('You have all the required permissions.') | Out-Null } + $ApplicationToken = Get-GraphToken -returnRefresh $true -SkipCache $true -AsApp $true + $ApplicationTokenDetails = Read-JwtAccessDetails -Token $ApplicationToken.access_token -erroraction SilentlyContinue | Select-Object + $LastUpdate = [DateTime]::SpecifyKind($GraphPermissions.Timestamp.DateTime, [DateTimeKind]::Utc) $CpvTable = Get-CippTable -tablename 'cpvtenants' $CpvRefresh = Get-CippAzDataTableEntity @CpvTable -Filter "PartitionKey eq 'Tenant'" @@ -162,13 +165,14 @@ function Test-CIPPAccessPermissions { } $AccessCheck = [PSCustomObject]@{ - AccessTokenDetails = $AccessTokenDetails - Messages = @($Messages) - ErrorMessages = @($ErrorMessages) - MissingPermissions = @($MissingPermissions) - CPVRefreshList = @($CPVRefreshList) - Links = @($Links) - Success = $Success + AccessTokenDetails = $AccessTokenDetails + ApplicationTokenDetails = $ApplicationTokenDetails + Messages = @($Messages) + ErrorMessages = @($ErrorMessages) + MissingPermissions = @($MissingPermissions) + CPVRefreshList = @($CPVRefreshList) + Links = @($Links) + Success = $Success } $Table = Get-CIPPTable -TableName AccessChecks From e688dd36ff3a097f100721f96e2558a63fe84363 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 4 Mar 2025 10:00:38 -0500 Subject: [PATCH 157/167] fix: tenant list links --- .../Administration/Tenant/Invoke-ListTenants.ps1 | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-ListTenants.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-ListTenants.ps1 index 0f432d56e54d..73ada77a4e13 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-ListTenants.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-ListTenants.ps1 @@ -41,7 +41,7 @@ Function Invoke-ListTenants { Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK Body = @{ - Results = @($GraphRequest) + Results = @($GraphRequest) Metadata = @{ Details = $Results } @@ -93,6 +93,19 @@ Function Invoke-ListTenants { } else { $Body = $Tenants } + if ($Request.Query.Mode -eq 'TenantList') { + # add portal link properties + $Body = $Body | Select-Object *, @{Name = 'portal_m365'; Expression = { "https://admin.microsoft.com/Partner/BeginClientSession.aspx?CTID=$($_.customerId)&CSDEST=o365admincenter" } }, + @{Name = 'portal_exchange'; Expression = { "https://admin.exchange.microsoft.com/?landingpage=homepage&form=mac_sidebar&delegatedOrg=$($_.defaultDomainName)" } }, + @{Name = 'portal_entra'; Expression = { "https://entra.microsoft.com/$($_.defaultDomainName)" } }, + @{Name = 'portal_teams'; Expression = { "https://admin.teams.microsoft.com/?delegatedOrg=$($_.defaultDomainName)" } }, + @{Name = 'portal_azure'; Expression = { "https://portal.azure.com/$($_.defaultDomainName)" } }, + @{Name = 'portal_intune'; Expression = { "https://intune.microsoft.com/$($_.defaultDomainName)" } }, + @{Name = 'portal_security'; Expression = { "https://security.microsoft.com/?tid=$($_.customerId)" } }, + @{Name = 'portal_compliance'; Expression = { "https://purview.microsoft.com/?tid=$($_.customerId)" } }, + @{Name = 'portal_sharepoint'; Expression = { "https://admin.microsoft.com/Partner/beginclientsession.aspx?CTID=$($_.customerId)&CSDEST=SharePoint" } } + } + } else { $body = $Tenants | Where-Object -Property defaultDomainName -EQ $Tenantfilter } From 2577a20a6dab3f3b5bd9586a5b6b665489750352 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 4 Mar 2025 11:07:07 -0500 Subject: [PATCH 158/167] fix: don't perform geo check with redacted IP --- Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 index 2623f399ca84..17638594eed1 100644 --- a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 @@ -94,7 +94,7 @@ function Test-CIPPAuditLogRules { } } - if ($Data.clientip) { + if ($Data.clientip -and $Data.clientip -notmatch '[X]+') { # Ignore IP addresses that have been redacted 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 } From d676afa6308f9f7d6e436f31f6555276d8474d4e Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 4 Mar 2025 11:52:09 -0500 Subject: [PATCH 159/167] chore: move audit log processing to separate timer function --- CIPPTimers.json | 12 +++++- .../Start-AuditLogOrchestrator.ps1 | 34 --------------- .../Start-AuditLogProcessingOrchestrator.ps1 | 42 +++++++++++++++++++ 3 files changed, 53 insertions(+), 35 deletions(-) create mode 100644 Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogProcessingOrchestrator.ps1 diff --git a/CIPPTimers.json b/CIPPTimers.json index 12988efc9c8c..0d53cf9bc154 100644 --- a/CIPPTimers.json +++ b/CIPPTimers.json @@ -35,12 +35,22 @@ "PreferredProcessor": "auditlog", "IsSystem": true }, + { + "Id": "01cd512a-15c4-44a9-b8cb-1e5d879cfd2d", + "Command": "Start-AuditLogProcessingOrchestrator", + "Description": "Orchestrator to process audit logs", + "Cron": "0 */15 * * * *", + "Priority": 3, + "RunOnProcessor": true, + "PreferredProcessor": "auditlog", + "IsSystem": true + }, { "Id": "03475c86-4314-4d7b-90f2-5a0639e3899b", "Command": "Start-AuditLogSearchCreation", "Description": "Timer to create audit log searches", "Cron": "0 */30 * * * *", - "Priority": 3, + "Priority": 4, "RunOnProcessor": true, "PreferredProcessor": "auditlog", "IsSystem": true diff --git a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 index 41a3053893db..e7010fd8fa0a 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1 @@ -29,40 +29,6 @@ function Start-AuditLogOrchestrator { SkipLog = $true } Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Depth 5 -Compress) - Write-Information 'Starting audit log processing in batches of 1000, per tenant' - $WebhookCacheTable = Get-CippTable -TableName 'CacheWebhooks' - $WebhookCache = Get-CIPPAzDataTableEntity @WebhookCacheTable - $TenantGroups = $WebhookCache | Group-Object -Property PartitionKey - - if ($TenantGroups) { - Write-Information "Processing webhook cache for $($TenantGroups.Count) tenants" - #Write-Warning "AuditLogJobs are: $($TenantGroups.Count) tenants. Tenants: $($TenantGroups.name | ConvertTo-Json -Compress) " - #Write-Warning "Here are the groups: $($TenantGroups | ConvertTo-Json -Compress)" - $ProcessQueue = New-CippQueueEntry -Name 'Audit Logs Process' -Reference 'AuditLogsProcess' -TotalTasks ($TenantGroups | Measure-Object -Property Count -Sum).Sum - $ProcessBatch = foreach ($TenantGroup in $TenantGroups) { - $TenantFilter = $TenantGroup.Name - $RowIds = @($TenantGroup.Group.RowKey) - for ($i = 0; $i -lt $RowIds.Count; $i += 1000) { - Write-Host "Processing $TenantFilter with $($RowIds.Count) row IDs. We're processing id $($RowIds[$i]) to $($RowIds[[Math]::Min($i + 999, $RowIds.Count - 1)])" - $BatchRowIds = $RowIds[$i..([Math]::Min($i + 999, $RowIds.Count - 1))] - [PSCustomObject]@{ - TenantFilter = $TenantFilter - RowIds = $BatchRowIds - QueueId = $ProcessQueue.RowKey - FunctionName = 'AuditLogTenantProcess' - } - } - } - if ($ProcessBatch) { - $ProcessInputObject = [PSCustomObject]@{ - OrchestratorName = 'AuditLogTenantProcess' - Batch = @($ProcessBatch) - SkipLog = $true - } - Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($ProcessInputObject | ConvertTo-Json -Depth 5 -Compress) - Write-Information "Started audit log processing orchestration with $($ProcessBatch.Count) batches" - } - } } } } catch { diff --git a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogProcessingOrchestrator.ps1 b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogProcessingOrchestrator.ps1 new file mode 100644 index 000000000000..e4eb7b779ddf --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogProcessingOrchestrator.ps1 @@ -0,0 +1,42 @@ +function Start-AuditLogProcessingOrchestrator { + <# + .SYNOPSIS + Start the Audit Log Processing Orchestrator + #> + [CmdletBinding(SupportsShouldProcess = $true)] + param() + Write-Information 'Starting audit log processing in batches of 1000, per tenant' + $WebhookCacheTable = Get-CippTable -TableName 'CacheWebhooks' + $WebhookCache = Get-CIPPAzDataTableEntity @WebhookCacheTable + $TenantGroups = $WebhookCache | Group-Object -Property PartitionKey + + if ($TenantGroups) { + Write-Information "Processing webhook cache for $($TenantGroups.Count) tenants" + #Write-Warning "AuditLogJobs are: $($TenantGroups.Count) tenants. Tenants: $($TenantGroups.name | ConvertTo-Json -Compress) " + #Write-Warning "Here are the groups: $($TenantGroups | ConvertTo-Json -Compress)" + $ProcessQueue = New-CippQueueEntry -Name 'Audit Logs Process' -Reference 'AuditLogsProcess' -TotalTasks ($TenantGroups | Measure-Object -Property Count -Sum).Sum + $ProcessBatch = foreach ($TenantGroup in $TenantGroups) { + $TenantFilter = $TenantGroup.Name + $RowIds = @($TenantGroup.Group.RowKey) + for ($i = 0; $i -lt $RowIds.Count; $i += 1000) { + Write-Host "Processing $TenantFilter with $($RowIds.Count) row IDs. We're processing id $($RowIds[$i]) to $($RowIds[[Math]::Min($i + 999, $RowIds.Count - 1)])" + $BatchRowIds = $RowIds[$i..([Math]::Min($i + 999, $RowIds.Count - 1))] + [PSCustomObject]@{ + TenantFilter = $TenantFilter + RowIds = $BatchRowIds + QueueId = $ProcessQueue.RowKey + FunctionName = 'AuditLogTenantProcess' + } + } + } + if ($ProcessBatch) { + $ProcessInputObject = [PSCustomObject]@{ + OrchestratorName = 'AuditLogTenantProcess' + Batch = @($ProcessBatch) + SkipLog = $true + } + Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($ProcessInputObject | ConvertTo-Json -Depth 5 -Compress) + Write-Information "Started audit log processing orchestration with $($ProcessBatch.Count) batches" + } + } +} From 0f4653c637155b94e64c885b112a4a48427e4f0f Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 4 Mar 2025 17:52:56 +0100 Subject: [PATCH 160/167] update cipptimers --- CIPPTimers.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CIPPTimers.json b/CIPPTimers.json index 0d53cf9bc154..51b0debdbb9f 100644 --- a/CIPPTimers.json +++ b/CIPPTimers.json @@ -28,7 +28,7 @@ { "Id": "44a40668-ed71-403c-8c26-b32e320086ad", "Command": "Start-AuditLogOrchestrator", - "Description": "Orchestrator to process audit logs", + "Description": "Orchestrator to download audit logs", "Cron": "0 */15 * * * *", "Priority": 2, "RunOnProcessor": true, From 5ce1dea110a6dc844abc442a1a330f7aafbf93c3 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 4 Mar 2025 18:19:31 +0100 Subject: [PATCH 161/167] Row Removal cleanup --- .../Webhooks/Test-CIPPAuditLogRules.ps1 | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 index 17638594eed1..1ba31ee67107 100644 --- a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 @@ -94,7 +94,8 @@ function Test-CIPPAuditLogRules { } } - if ($Data.clientip -and $Data.clientip -notmatch '[X]+') { # Ignore IP addresses that have been redacted + if ($Data.clientip -and $Data.clientip -notmatch '[X]+') { + # Ignore IP addresses that have been redacted 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 } @@ -169,13 +170,9 @@ function Test-CIPPAuditLogRules { Write-Host "Removing row $($AuditRecord.id) from cache" try { Write-Information 'Removing processed rows from cache' - if ($AuditRecord.id) { - $RowEntity = Get-CIPPAzDataTableEntity @CacheWebhooksTable -Filter "PartitionKey eq '$TenantFilter' and RowKey eq '$($AuditRecord.id)'" - if ($RowEntity) { - Remove-AzDataTableEntity @CacheWebhooksTable -Entity $RowEntity -Force - Write-Information "Removed row $($AuditRecord.id) from cache" - } - } + $RowEntity = Get-CIPPAzDataTableEntity @CacheWebhooksTable -Filter "PartitionKey eq '$TenantFilter' and RowKey eq '$($AuditRecord.id)'" + Remove-AzDataTableEntity @CacheWebhooksTable -Entity $RowEntity -Force + Write-Information "Removed row $($AuditRecord.id) from cache" } catch { Write-Information "Error removing rows from cache: $($_.Exception.Message)" } @@ -252,5 +249,20 @@ function Test-CIPPAuditLogRules { } } + try { + Write-Information 'Removing processed rows from cache' + foreach ($Row in $Rows) { + if ($Row.id) { + $RowEntity = Get-CIPPAzDataTableEntity @CacheWebhooksTable -Filter "PartitionKey eq '$TenantFilter' and RowKey eq '$($Row.id)'" + if ($RowEntity) { + Remove-AzDataTableEntity @CacheWebhooksTable -Entity $RowEntity -Force + Write-Information "Removed row $($Row.id) from cache at final pass." + } + } + } + } catch { + Write-Information "Error removing rows from cache: $($_.Exception.Message)" + } + return $Results } From 0d979fd3fcdddc4ebc9bdd482d8cdf5282fbc460 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 4 Mar 2025 12:20:27 -0500 Subject: [PATCH 162/167] fix: halopsa hash title for RowKey --- Modules/CippExtensions/Public/Halo/New-HaloPSATicket.ps1 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Modules/CippExtensions/Public/Halo/New-HaloPSATicket.ps1 b/Modules/CippExtensions/Public/Halo/New-HaloPSATicket.ps1 index f1378374ee0d..4b79384771d8 100644 --- a/Modules/CippExtensions/Public/Halo/New-HaloPSATicket.ps1 +++ b/Modules/CippExtensions/Public/Halo/New-HaloPSATicket.ps1 @@ -10,9 +10,11 @@ function New-HaloPSATicket { $Configuration = ((Get-CIPPAzDataTableEntity @Table).config | ConvertFrom-Json).HaloPSA $TicketTable = Get-CIPPTable -TableName 'PSATickets' $token = Get-HaloToken -configuration $Configuration + # sha hash title + $TitleHash = Get-StringHash -String $title if ($Configuration.ConsolidateTickets) { - $ExistingTicket = Get-CIPPAzDataTableEntity @TicketTable -Filter "PartitionKey eq 'HaloPSA' and RowKey eq '$($client)-$($title)'" + $ExistingTicket = Get-CIPPAzDataTableEntity @TicketTable -Filter "PartitionKey eq 'HaloPSA' and RowKey eq '$($client)-$($TitleHash)'" if ($ExistingTicket) { Write-Information "Ticket already exists in HaloPSA: $($ExistingTicket.TicketID)" @@ -83,7 +85,9 @@ function New-HaloPSATicket { if ($Configuration.ConsolidateTickets) { $TicketObject = [PSCustomObject]@{ PartitionKey = 'HaloPSA' - RowKey = "$($client)-$($title)" + RowKey = "$($client)-$($TitleHash)" + Title = $title + ClientId = $client TicketID = $Ticket.id } Add-CIPPAzDataTableEntity @TicketTable -Entity $TicketObject -Force From be63bbef7a5399cd0c66d72df26b8d72ab09262e Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 4 Mar 2025 18:38:00 +0100 Subject: [PATCH 163/167] fixes edit user bugs --- .../Identity/Administration/Users/Invoke-EditUser.ps1 | 2 +- Modules/CIPPCore/Public/New-CippUser.ps1 | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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 a7fa34715afb..7c88fa1588fd 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 @@ -34,7 +34,7 @@ Function Invoke-EditUser { #Edit the user try { Write-Host "$([boolean]$UserObj.MustChangePass)" - $UserPrincipalName = "$($UserObj.Username ? $UserObj.username :$UserObj.mailNickname)@$($UserObj.Domain ? $UserObj.Domain : $UserObj.primDomain.value)" + $UserPrincipalName = "$($UserObj.username)@$($UserObj.Domain ? $UserObj.Domain : $UserObj.primDomain.value)" $BodyToship = [pscustomobject] @{ 'givenName' = $UserObj.givenName 'surname' = $UserObj.surname diff --git a/Modules/CIPPCore/Public/New-CippUser.ps1 b/Modules/CIPPCore/Public/New-CippUser.ps1 index 234c9392ba03..b741a161bded 100644 --- a/Modules/CIPPCore/Public/New-CippUser.ps1 +++ b/Modules/CIPPCore/Public/New-CippUser.ps1 @@ -13,7 +13,7 @@ function New-CIPPUser { Write-Host $UserObj.PrimDomain.value $Aliases = ($UserObj.AddedAliases) -split '\s' $password = if ($UserObj.password) { $UserObj.password } else { New-passwordString } - $UserprincipalName = "$($UserObj.Username ? $userobj.username :$userobj.mailNickname )@$($UserObj.Domain ? $UserObj.Domain : $UserObj.PrimDomain.value)" + $UserprincipalName = "$($userobj.username)@$($UserObj.Domain ? $UserObj.Domain : $UserObj.PrimDomain.value)" Write-Host "Creating user $UserprincipalName" Write-Host "tenant filter is $($UserObj.tenantFilter)" $BodyToship = [pscustomobject] @{ @@ -22,7 +22,7 @@ function New-CIPPUser { 'accountEnabled' = $true 'displayName' = $UserObj.displayName 'department' = $UserObj.Department - 'mailNickname' = $UserObj.Username ? $userobj.username :$userobj.mailNickname + 'mailNickname' = $UserObj.Username ? $userobj.username : $userobj.mailNickname 'userPrincipalName' = $UserprincipalName 'usageLocation' = $UserObj.usageLocation.value ? $UserObj.usageLocation.value : $UserObj.usageLocation 'city' = $UserObj.City From ab0343d57138038558a12617341576f8438aa3dc Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 4 Mar 2025 18:51:41 +0100 Subject: [PATCH 164/167] up version --- version_latest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version_latest.txt b/version_latest.txt index 429dc57af3a3..1502020768a7 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -7.2.3 +7.3.0 From ae79a29cb33fb3e9b7410ba6cf1ca8882213c97a Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 4 Mar 2025 18:55:51 +0100 Subject: [PATCH 165/167] deleted unneeded workflows --- .github/workflows/dev_cipp44thq.yml | 30 -------------------- .github/workflows/dev_cippbcaom.yml | 30 -------------------- .github/workflows/dev_cippjta72-proc.yml | 30 -------------------- .github/workflows/dev_cippjta72.yml | 30 -------------------- .github/workflows/dev_cippkwn4s-auditlog.yml | 30 -------------------- .github/workflows/dev_cippkwn4s.yml | 30 -------------------- 6 files changed, 180 deletions(-) delete mode 100644 .github/workflows/dev_cipp44thq.yml delete mode 100644 .github/workflows/dev_cippbcaom.yml delete mode 100644 .github/workflows/dev_cippjta72-proc.yml delete mode 100644 .github/workflows/dev_cippjta72.yml delete mode 100644 .github/workflows/dev_cippkwn4s-auditlog.yml delete mode 100644 .github/workflows/dev_cippkwn4s.yml diff --git a/.github/workflows/dev_cipp44thq.yml b/.github/workflows/dev_cipp44thq.yml deleted file mode 100644 index f21a9de0596d..000000000000 --- a/.github/workflows/dev_cipp44thq.yml +++ /dev/null @@ -1,30 +0,0 @@ -# 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 - cipp44thq - -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 - - steps: - - name: 'Checkout GitHub Action' - uses: actions/checkout@v4 - - - name: 'Run Azure Functions Action' - uses: Azure/functions-action@v1 - id: fa - with: - app-name: 'cipp44thq' - slot-name: 'Production' - package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }} - publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_2EBCA6FEB5E54403AE417859C5D28817 }} \ No newline at end of file diff --git a/.github/workflows/dev_cippbcaom.yml b/.github/workflows/dev_cippbcaom.yml deleted file mode 100644 index c4bcf1198e74..000000000000 --- a/.github/workflows/dev_cippbcaom.yml +++ /dev/null @@ -1,30 +0,0 @@ -# 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 - cippbcaom - -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 - - steps: - - name: 'Checkout GitHub Action' - uses: actions/checkout@v4 - - - name: 'Run Azure Functions Action' - uses: Azure/functions-action@v1 - id: fa - with: - app-name: 'cippbcaom' - slot-name: 'Production' - package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }} - publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_0FE8CACBBF7D409DAAF132988BECEC4B }} \ No newline at end of file diff --git a/.github/workflows/dev_cippjta72-proc.yml b/.github/workflows/dev_cippjta72-proc.yml deleted file mode 100644 index 530581163549..000000000000 --- a/.github/workflows/dev_cippjta72-proc.yml +++ /dev/null @@ -1,30 +0,0 @@ -# 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 - cippjta72-proc - -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 - - steps: - - name: 'Checkout GitHub Action' - uses: actions/checkout@v4 - - - name: 'Run Azure Functions Action' - uses: Azure/functions-action@v1 - id: fa - with: - app-name: 'cippjta72-proc' - slot-name: 'Production' - package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }} - publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_A53AC5C52A55459DA0A3D8F1716638CB }} \ No newline at end of file diff --git a/.github/workflows/dev_cippjta72.yml b/.github/workflows/dev_cippjta72.yml deleted file mode 100644 index 23c0cd3668d6..000000000000 --- a/.github/workflows/dev_cippjta72.yml +++ /dev/null @@ -1,30 +0,0 @@ -# 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 - cippjta72 - -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 - - steps: - - name: 'Checkout GitHub Action' - uses: actions/checkout@v4 - - - name: 'Run Azure Functions Action' - uses: Azure/functions-action@v1 - id: fa - with: - app-name: 'cippjta72' - slot-name: 'Production' - package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }} - publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_5B44448119C645C099EE192346D7433A }} \ No newline at end of file diff --git a/.github/workflows/dev_cippkwn4s-auditlog.yml b/.github/workflows/dev_cippkwn4s-auditlog.yml deleted file mode 100644 index a6087052d3ad..000000000000 --- a/.github/workflows/dev_cippkwn4s-auditlog.yml +++ /dev/null @@ -1,30 +0,0 @@ -# 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 - cippkwn4s-auditlog - -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 - - steps: - - name: 'Checkout GitHub Action' - uses: actions/checkout@v4 - - - name: 'Run Azure Functions Action' - uses: Azure/functions-action@v1 - id: fa - with: - app-name: 'cippkwn4s-auditlog' - slot-name: 'Production' - package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }} - publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_34E06457AFD540C5ADCC893F70B5C245 }} \ No newline at end of file diff --git a/.github/workflows/dev_cippkwn4s.yml b/.github/workflows/dev_cippkwn4s.yml deleted file mode 100644 index 904a72f5e546..000000000000 --- a/.github/workflows/dev_cippkwn4s.yml +++ /dev/null @@ -1,30 +0,0 @@ -# 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 - cippkwn4s - -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 - - steps: - - name: 'Checkout GitHub Action' - uses: actions/checkout@v4 - - - name: 'Run Azure Functions Action' - uses: Azure/functions-action@v1 - id: fa - with: - app-name: 'cippkwn4s' - slot-name: 'Production' - package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }} - publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_D3DB920CED0443B791B30C72BBB395BE }} \ No newline at end of file From 54c2721d38e4aca09d541b4ec3662b8f95ea94ba Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 4 Mar 2025 18:57:57 +0100 Subject: [PATCH 166/167] clean changes --- .github/workflows/dev_api.yml | 30 ++++++++++++++++++++++++++++++ .github/workflows/dev_api_proc.yml | 30 ++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 .github/workflows/dev_api.yml create mode 100644 .github/workflows/dev_api_proc.yml diff --git a/.github/workflows/dev_api.yml b/.github/workflows/dev_api.yml new file mode 100644 index 000000000000..3676a3b78e32 --- /dev/null +++ b/.github/workflows/dev_api.yml @@ -0,0 +1,30 @@ +# 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: dev_api + +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 + + steps: + - name: 'Checkout GitHub Action' + uses: actions/checkout@v4 + + - name: 'Run Azure Functions Action' + uses: Azure/functions-action@v1 + id: fa + with: + app-name: 'cippjta72' + slot-name: 'Production' + package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }} + publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_5B44448119C645C099EE192346D7433A }} diff --git a/.github/workflows/dev_api_proc.yml b/.github/workflows/dev_api_proc.yml new file mode 100644 index 000000000000..d9e00f857815 --- /dev/null +++ b/.github/workflows/dev_api_proc.yml @@ -0,0 +1,30 @@ +# 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: dev_api_proc + +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 + + steps: + - name: 'Checkout GitHub Action' + uses: actions/checkout@v4 + + - name: 'Run Azure Functions Action' + uses: Azure/functions-action@v1 + id: fa + with: + app-name: 'cippjta72-proc' + slot-name: 'Production' + package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }} + publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_A53AC5C52A55459DA0A3D8F1716638CB }} From 76325474a4e2298b409b93d01d6064d5e09381ee Mon Sep 17 00:00:00 2001 From: KelvinTegelaar <49186168+KelvinTegelaar@users.noreply.github.com> Date: Tue, 4 Mar 2025 18:58:10 +0100 Subject: [PATCH 167/167] changes --- .github/workflows/dev_api.yml | 1 + .github/workflows/dev_api_proc.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/dev_api.yml b/.github/workflows/dev_api.yml index 3676a3b78e32..47181a0b2f68 100644 --- a/.github/workflows/dev_api.yml +++ b/.github/workflows/dev_api.yml @@ -14,6 +14,7 @@ env: jobs: deploy: + if: github.event.repository.fork == false && github.event_name == 'push' runs-on: windows-latest steps: diff --git a/.github/workflows/dev_api_proc.yml b/.github/workflows/dev_api_proc.yml index d9e00f857815..61591158e040 100644 --- a/.github/workflows/dev_api_proc.yml +++ b/.github/workflows/dev_api_proc.yml @@ -14,6 +14,7 @@ env: jobs: deploy: + if: github.event.repository.fork == false && github.event_name == 'push' runs-on: windows-latest steps: