diff --git a/.github/workflows/dev_cipppwrro.yml b/.github/workflows/dev_cipppwrro.yml deleted file mode 100644 index a62bd3026748..000000000000 --- a/.github/workflows/dev_cipppwrro.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 - cipppwrro - -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: 'cipppwrro' - slot-name: 'Production' - package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }} - publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_D5D7DFF930C04B519206F25DDCD88324 }} \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json index c2795fa0dd8c..46245188b38e 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,5 +1,6 @@ -{ - "recommendations": [ - "editorconfig.editorconfig" - ] -} +{ + "recommendations": [ + "editorconfig.editorconfig", + "streetsidesoftware.code-spell-checker" + ] +} diff --git a/AddChocoApp/IntunePackage/Install.ps1 b/AddChocoApp/IntunePackage/Install.ps1 index 5569e9ec5e02..fd5e86dfc71e 100644 --- a/AddChocoApp/IntunePackage/Install.ps1 +++ b/AddChocoApp/IntunePackage/Install.ps1 @@ -19,13 +19,13 @@ param ( try { if ($Trace) { Start-Transcript -Path (Join-Path $env:windir "\temp\choco-$Packagename-trace.log") } - $chocoPath = "$($ENV:SystemDrive)\ProgramData\chocolatey\bin\choco.exe" + $chocoPath = "$($env:SystemDrive)\ProgramData\chocolatey\bin\choco.exe" if ($InstallChoco) { if (-not (Test-Path $chocoPath)) { try { Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) - $chocoPath = "$($ENV:SystemDrive)\ProgramData\chocolatey\bin\choco.exe" + $chocoPath = "$($env:SystemDrive)\ProgramData\chocolatey\bin\choco.exe" } catch { Write-Host "InstallChoco Error: $($_.Exception.Message)" @@ -45,7 +45,7 @@ try { & "$chocoPath" install $Packagename -y $CustomRepoString } Write-Host 'Completed.' - } + } catch { Write-Host "Install/upgrade error: $($_.Exception.Message)" } diff --git a/AddChocoApp/IntunePackage/Uninstall.ps1 b/AddChocoApp/IntunePackage/Uninstall.ps1 index 949dceeaf8ea..9d1512fabcfc 100644 --- a/AddChocoApp/IntunePackage/Uninstall.ps1 +++ b/AddChocoApp/IntunePackage/Uninstall.ps1 @@ -4,6 +4,6 @@ param ( [string] $Packagename ) -$chocoPath = "$($ENV:SystemDrive)\ProgramData\chocolatey\bin\choco.exe" +$chocoPath = "$($env:SystemDrive)\ProgramData\chocolatey\bin\choco.exe" & $Chocopath uninstall $Packagename -y diff --git a/Config/standards.json b/Config/standards.json index 70d9710628db..92ef2e2806f5 100644 --- a/Config/standards.json +++ b/Config/standards.json @@ -2,7 +2,7 @@ { "name": "standards.MailContacts", "cat": "Global Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Defines the email address to receive general updates and information related to M365 subscriptions. Leave a contact field blank if you do not want to update the contact information.", "docsDescription": "", "addedComponent": [ @@ -34,30 +34,32 @@ "label": "Set contact e-mails", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2022-03-13", "powershellEquivalent": "Set-MsolCompanyContactInformation", "recommendedBy": [] }, { "name": "standards.AuditLog", "cat": "Global Standards", - "tag": ["lowimpact", "CIS", "mip_search_auditlog"], + "tag": ["CIS", "mip_search_auditlog"], "helpText": "Enables the Unified Audit Log for tracking and auditing activities. Also runs Enable-OrganizationCustomization if necessary.", "addedComponent": [], "label": "Enable the Unified Audit Log", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2021-11-16", "powershellEquivalent": "Enable-OrganizationCustomization", - "recommendedBy": ["CIS"] + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.ProfilePhotos", "cat": "Global Standards", - "tag": ["lowimpact"], + "tag": [], "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.", "addedComponent": [ { - "type": "select", + "type": "autoComplete", "multiple": false, "creatable": false, "label": "Select value", @@ -77,18 +79,20 @@ "label": "Allow users to set profile photos", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2025-01-19", "powershellEquivalent": "Set-OrganizationConfig -ProfilePhotoOptions EnablePhotos and Update-MgBetaAdminPeople", "recommendedBy": [] }, { "name": "standards.PhishProtection", "cat": "Global Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Adds branding to the logon page that only appears if the url is not login.microsoftonline.com. This potentially prevents AITM attacks via EvilNginx. This will also automatically generate alerts if a clone of your login page has been found when set to Remediate.", "addedComponent": [], "label": "Enable Phishing Protection system via branding CSS", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-01-22", "disabledFeatures": { "report": true, "warn": true, @@ -100,7 +104,7 @@ { "name": "standards.Branding", "cat": "Global Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Sets the branding for the tenant. This includes the login page, and the Office 365 portal.", "addedComponent": [ { @@ -121,7 +125,7 @@ "label": "Hide self-service password reset" }, { - "type": "select", + "type": "autoComplete", "multiple": false, "label": "Visual Template", "name": "standards.Branding.layoutTemplateType", @@ -150,81 +154,87 @@ "label": "Set branding for the tenant", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-05-13", "powershellEquivalent": "Portal only", "recommendedBy": [] }, { "name": "standards.EnableCustomerLockbox", "cat": "Global Standards", - "tag": ["lowimpact", "CIS", "CustomerLockBoxEnabled"], + "tag": ["CIS", "CustomerLockBoxEnabled"], "helpText": "Enables Customer Lockbox that offers an approval process for Microsoft support to access organization data", "docsDescription": "Customer Lockbox ensures that Microsoft can't access your content to do service operations without your explicit approval. Customer Lockbox ensures only authorized requests allow access to your organizations data.", "addedComponent": [], "label": "Enable Customer Lockbox", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-01-08", "powershellEquivalent": "Set-OrganizationConfig -CustomerLockBoxEnabled $true", "recommendedBy": ["CIS"] }, { "name": "standards.EnablePronouns", "cat": "Global Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Enables the Pronouns feature for the tenant. This allows users to set their pronouns in their profile.", "addedComponent": [], "label": "Enable Pronouns", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-06-05", "powershellEquivalent": "Update-MgBetaAdminPeoplePronoun -IsEnabledInOrganization:$true", "recommendedBy": [] }, { "name": "standards.AnonReportDisable", "cat": "Global Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Shows usernames instead of pseudo anonymised names in reports. This standard is required for reporting to work correctly.", "docsDescription": "Microsoft announced some APIs and reports no longer return names, to comply with compliance and legal requirements in specific countries. This proves an issue for a lot of MSPs because those reports are often helpful for engineers. This standard applies a setting that shows usernames in those API calls / reports.", "addedComponent": [], "label": "Enable Usernames instead of pseudo anonymised names in reports", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2021-11-16", "powershellEquivalent": "Update-MgBetaAdminReportSetting -BodyParameter @{displayConcealedNames = $true}", - "recommendedBy": [] + "recommendedBy": ["CIPP"] }, { "name": "standards.DisableGuestDirectory", "cat": "Global Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Disables Guest access to enumerate directory objects. This prevents guest users from seeing other users or guests in the directory.", "docsDescription": "Sets it so guests can view only their own user profile. Permission to view other users isn't allowed. Also restricts guest users from seeing the membership of groups they're in. See exactly what get locked down in the [Microsoft documentation.](https://learn.microsoft.com/en-us/entra/fundamentals/users-default-permissions)", "addedComponent": [], "label": "Restrict guest user access to directory objects", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2022-05-04", "powershellEquivalent": "Set-AzureADMSAuthorizationPolicy -GuestUserRoleId '2af84b1e-32c8-42b7-82bc-daa82404023b'", - "recommendedBy": [] + "recommendedBy": ["CIPP"] }, { "name": "standards.DisableBasicAuthSMTP", "cat": "Global Standards", - "tag": ["mediumimpact"], - "helpText": "Disables SMTP AUTH for the organization and all users. This is the default for new tenants. ", + "tag": [], + "helpText": "Disables SMTP AUTH for the organization and all users. This is the default for new tenants.", "docsDescription": "Disables SMTP basic authentication for the tenant and all users with it explicitly enabled.", "addedComponent": [], "label": "Disable SMTP Basic Authentication", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2021-11-16", "powershellEquivalent": "Set-TransportConfig -SmtpClientAuthenticationDisabled $true", - "recommendedBy": [] + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.ActivityBasedTimeout", "cat": "Global Standards", - "tag": ["mediumimpact", "CIS", "spo_idle_session_timeout"], + "tag": ["CIS", "spo_idle_session_timeout"], "helpText": "Enables and sets Idle session timeout for Microsoft 365 to 1 hour. This policy affects most M365 web apps", "addedComponent": [ { - "type": "select", + "type": "autoComplete", "multiple": false, "creatable": false, "label": "Select value", @@ -256,13 +266,14 @@ "label": "Enable Activity based Timeout", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2022-04-13", "powershellEquivalent": "Portal or Graph API", "recommendedBy": ["CIS"] }, { "name": "standards.AuthMethodsSettings", "cat": "Entra (AAD) Standards", - "tag": ["lowimpact"], + "tag": [], "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.", "addedComponent": [ @@ -314,13 +325,14 @@ "label": "Configure Authentication Methods Policy Settings", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2025-02-10", "powershellEquivalent": "Update-MgBetaPolicyAuthenticationMethodPolicy", "recommendedBy": [] }, { "name": "standards.AppDeploy", "cat": "Entra (AAD) Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Deploys selected applications to the tenant. Use a comma separated list of application IDs to deploy multiple applications. Permissions will be copied from the source application.", "docsDescription": "Uses the CIPP functionality that deploys applications across an entire tenant base as a standard.", "addedComponent": [ @@ -333,57 +345,61 @@ "label": "Deploy Application", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-07-07", "powershellEquivalent": "Portal or Graph API", "recommendedBy": [] }, { "name": "standards.laps", "cat": "Entra (AAD) Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Enables the tenant to use LAPS. You must still create a policy for LAPS to be active on all devices. Use the template standards to deploy this by default.", "docsDescription": "Enables the LAPS functionality on the tenant. Prerequisite for using Windows LAPS via Azure AD.", "addedComponent": [], "label": "Enable LAPS on the tenant", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2023-04-25", "powershellEquivalent": "Portal or Graph API", - "recommendedBy": [] + "recommendedBy": ["CIPP"] }, { "name": "standards.PWdisplayAppInformationRequiredState", "cat": "Entra (AAD) Standards", - "tag": ["lowimpact", "CIS"], + "tag": ["CIS"], "helpText": "Enables the MS authenticator app to display information about the app that is requesting authentication. This displays the application name.", "docsDescription": "Allows users to use Passwordless with Number Matching and adds location information from the last request", "addedComponent": [], "label": "Enable Passwordless with Location information and Number Matching", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2021-11-16", "powershellEquivalent": "Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration", "recommendedBy": ["CIS"] }, { "name": "standards.allowOTPTokens", "cat": "Entra (AAD) Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Allows you to use MS authenticator OTP token generator", "docsDescription": "Allows you to use Microsoft Authenticator OTP token generator. Useful for using the NPS extension as MFA on VPN clients.", "addedComponent": [], "label": "Enable OTP via Authenticator", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2023-12-06", "powershellEquivalent": "Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration", "recommendedBy": [] }, { "name": "standards.PWcompanionAppAllowedState", "cat": "Entra (AAD) Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Sets the state of Authenticator Lite, Authenticator lite is a companion app for passwordless authentication.", "docsDescription": "Sets the Authenticator Lite state to enabled. This allows users to use the Authenticator Lite built into the Outlook app instead of the full Authenticator app.", "addedComponent": [ { - "type": "select", + "type": "autoComplete", "multiple": false, "creatable": false, "label": "Select value", @@ -403,57 +419,61 @@ "label": "Set Authenticator Lite state", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2023-05-18", "powershellEquivalent": "Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration", "recommendedBy": [] }, { "name": "standards.EnableFIDO2", "cat": "Entra (AAD) Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Enables the FIDO2 authenticationMethod for the tenant", "docsDescription": "Enables FIDO2 capabilities for the tenant. This allows users to use FIDO2 keys like a Yubikey for authentication.", "addedComponent": [], "label": "Enable FIDO2 capabilities", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2022-12-08", "powershellEquivalent": "Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration", - "recommendedBy": [] + "recommendedBy": ["CIPP"] }, { "name": "standards.EnableHardwareOAuth", "cat": "Entra (AAD) Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Enables the HardwareOath authenticationMethod for the tenant. This allows you to use hardware tokens for generating 6 digit MFA codes.", "docsDescription": "Enables Hardware OAuth tokens for the tenant. This allows users to use hardware tokens like a Yubikey for authentication.", "addedComponent": [], "label": "Enable Hardware OAuth tokens", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2023-12-18", "powershellEquivalent": "Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration", "recommendedBy": [] }, { "name": "standards.allowOAuthTokens", "cat": "Entra (AAD) Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Allows you to use any software OAuth token generator", "docsDescription": "Enables OTP Software OAuth tokens for the tenant. This allows users to use OTP codes generated via software, like a password manager to be used as an authentication method.", "addedComponent": [], "label": "Enable OTP Software OAuth tokens", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2022-12-18", "powershellEquivalent": "Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration", "recommendedBy": [] }, { "name": "standards.TAP", "cat": "Entra (AAD) Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Enables TAP and sets the default TAP lifetime to 1 hour. This configuration also allows you to select if a TAP is single use or multi-logon.", "docsDescription": "Enables Temporary Password generation for the tenant.", "addedComponent": [ { - "type": "select", + "type": "autoComplete", "multiple": false, "creatable": false, "label": "Select TAP Lifetime", @@ -473,30 +493,32 @@ "label": "Enable Temporary Access Passwords", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2022-03-15", "powershellEquivalent": "Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration", - "recommendedBy": [] + "recommendedBy": ["CIPP"] }, { "name": "standards.PasswordExpireDisabled", "cat": "Entra (AAD) Standards", - "tag": ["lowimpact", "CIS", "PWAgePolicyNew"], + "tag": ["CIS", "PWAgePolicyNew"], "helpText": "Disables the expiration of passwords for the tenant by setting the password expiration policy to never expire for any user.", "docsDescription": "Sets passwords to never expire for tenant, recommended to use in conjunction with secure password requirements.", "addedComponent": [], "label": "Do not expire passwords", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2021-11-16", "powershellEquivalent": "Update-MgDomain", - "recommendedBy": ["CIS"] + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.ExternalMFATrusted", "cat": "Entra (AAD) Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Sets the state of the Cross-tenant access setting to trust external MFA. This allows guest users to use their home tenant MFA to access your tenant.", "addedComponent": [ { - "type": "select", + "type": "autoComplete", "multiple": false, "creatable": false, "label": "Select value", @@ -516,26 +538,28 @@ "label": "Sets the Cross-tenant access setting to trust external MFA", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-03-26", "powershellEquivalent": "Update-MgBetaPolicyCrossTenantAccessPolicyDefault", "recommendedBy": [] }, { "name": "standards.DisableTenantCreation", "cat": "Entra (AAD) Standards", - "tag": ["lowimpact", "CIS"], - "helpText": "Restricts creation of M365 tenants to the Global Administrator or Tenant Creator roles. ", + "tag": ["CIS"], + "helpText": "Restricts creation of M365 tenants to the Global Administrator or Tenant Creator roles.", "docsDescription": "Users by default are allowed to create M365 tenants. This disables that so only admins can create new M365 tenants.", "addedComponent": [], "label": "Disable M365 Tenant creation by users", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2022-11-29", "powershellEquivalent": "Update-MgPolicyAuthorizationPolicy", - "recommendedBy": ["CIS"] + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.EnableAppConsentRequests", "cat": "Entra (AAD) Standards", - "tag": ["lowimpact", "CIS"], + "tag": ["CIS"], "helpText": "Enables App consent admin requests for the tenant via the GA role. Does not overwrite existing reviewer settings", "docsDescription": "Enables the ability for users to request admin consent for applications. Should be used in conjunction with the \"Require admin consent for applications\" standards", "addedComponent": [ @@ -548,18 +572,19 @@ "label": "Enable App consent admin requests", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2023-11-27", "powershellEquivalent": "Update-MgPolicyAdminConsentRequestPolicy", "recommendedBy": ["CIS"] }, { "name": "standards.NudgeMFA", "cat": "Entra (AAD) Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Sets the state of the registration campaign for the tenant", "docsDescription": "Sets the state of the registration campaign for the tenant. If enabled nudges users to set up the Microsoft Authenticator during sign-in.", "addedComponent": [ { - "type": "select", + "type": "autoComplete", "multiple": false, "creatable": false, "label": "Select value", @@ -579,69 +604,74 @@ "type": "number", "name": "standards.NudgeMFA.snoozeDurationInDays", "label": "Number of days to allow users to skip registering Authenticator (0-14, default is 1)", - "default": 1 + "defaultValue": 1 } ], "label": "Sets the state for the request to setup Authenticator", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2022-12-08", "powershellEquivalent": "Update-MgPolicyAuthenticationMethodPolicy", "recommendedBy": [] }, { "name": "standards.DisableM365GroupUsers", "cat": "Entra (AAD) Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Restricts M365 group creation to certain admin roles. This disables the ability to create Teams, SharePoint sites, Planner, etc", "docsDescription": "Users by default are allowed to create M365 groups. This restricts M365 group creation to certain admin roles. This disables the ability to create Teams, SharePoint sites, Planner, etc", "addedComponent": [], "label": "Disable M365 Group creation by users", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2022-07-17", "powershellEquivalent": "Update-MgBetaDirectorySetting", "recommendedBy": [] }, { "name": "standards.DisableAppCreation", "cat": "Entra (AAD) Standards", - "tag": ["lowimpact", "CIS"], + "tag": ["CIS"], "helpText": "Disables the ability for users to create App registrations in the tenant.", "docsDescription": "Disables the ability for users to create applications in Entra. Done to prevent breached accounts from creating an app to maintain access to the tenant, even after the breached account has been secured.", "addedComponent": [], "label": "Disable App creation by users", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-03-20", "powershellEquivalent": "Update-MgPolicyAuthorizationPolicy", - "recommendedBy": ["CIS"] + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.DisableSecurityGroupUsers", "cat": "Entra (AAD) Standards", - "tag": ["mediumimpact"], + "tag": [], "helpText": "Completely disables the creation of security groups by users. This also breaks the ability to manage groups themselves, or create Teams", "addedComponent": [], "label": "Disable Security Group creation by users", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2022-07-17", "powershellEquivalent": "Update-MgBetaPolicyAuthorizationPolicy", "recommendedBy": [] }, { "name": "standards.LegacyMFACleanup", "cat": "Entra (AAD) Standards", - "tag": ["mediumimpact"], + "tag": [], "helpText": "This standard currently does not function and can be safely disabled", "addedComponent": [], "label": "Remove Legacy MFA if SD or CA is active", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2021-11-16", "powershellEquivalent": "Set-MsolUser -StrongAuthenticationRequirements $null", "recommendedBy": [] }, { "name": "standards.DisableSelfServiceLicenses", "cat": "Entra (AAD) Standards", - "tag": ["mediumimpact"], + "tag": [], "helpText": "This standard disables all self service licenses and enables all exclusions", "addedComponent": [ { @@ -654,25 +684,27 @@ "label": "Disable Self Service Licensing", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2021-11-16", "powershellEquivalent": "Set-MsolCompanySettings -AllowAdHocSubscriptions $false", "recommendedBy": [] }, { "name": "standards.DisableGuests", "cat": "Entra (AAD) Standards", - "tag": ["mediumimpact"], + "tag": [], "helpText": "Blocks login for guest users that have not logged in for 90 days", "addedComponent": [], "label": "Disable Guest accounts that have not logged on for 90 days", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2022-10-20", "powershellEquivalent": "Graph API", - "recommendedBy": [] + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.OauthConsent", "cat": "Entra (AAD) Standards", - "tag": ["mediumimpact", "CIS"], + "tag": ["CIS"], "helpText": "Disables users from being able to consent to applications, except for those specified in the field below", "docsDescription": "Requires users to get administrator consent before sharing data with applications. You can preapprove specific applications.", "addedComponent": [ @@ -686,25 +718,27 @@ "label": "Require admin consent for applications (Prevent OAuth phishing)", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2021-11-16", "powershellEquivalent": "Update-MgPolicyAuthorizationPolicy", - "recommendedBy": ["CIS"] + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.OauthConsentLowSec", "cat": "Entra (AAD) Standards", - "tag": ["mediumimpact", "IntegratedApps"], + "tag": ["IntegratedApps"], "helpText": "Sets the default oauth consent level so users can consent to applications that have low risks.", "docsDescription": "Allows users to consent to applications with low assigned risk.", "label": "Allow users to consent to applications with low security risk (Prevent OAuth phishing. Lower impact, less secure)", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2022-08-16", "powershellEquivalent": "Update-MgPolicyAuthorizationPolicy", "recommendedBy": [] }, { "name": "standards.GuestInvite", "cat": "Entra (AAD) Standards", - "tag": ["mediumimpact"], + "tag": [], "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.", "addedComponent": [ { @@ -737,20 +771,21 @@ "label": "Guest Invite setting", "impact": "Medium Impact", "impactColour": "warning", - "powershellEquivalent": "", + "addedDate": "2024-11-12", + "powershellEquivalent": "Graph API", "recommendedBy": [] }, { "name": "standards.StaleEntraDevices", "cat": "Entra (AAD) Standards", - "tag": ["highimpact", "CIS"], + "tag": ["CIS"], "helpText": "Cleans up Entra devices that have not connected/signed in for the specified number of days.", "docsDescription": "Cleans up Entra devices that have not connected/signed in for the specified number of days. First disables and later deletes the devices. More info can be found in the [Microsoft documentation](https://learn.microsoft.com/en-us/entra/identity/devices/manage-stale-devices)", "addedComponent": [ { "type": "number", "name": "standards.StaleEntraDevices.deviceAgeThreshold", - "label": "Days before stale(Dont set below 30)" + "label": "Days before stale(Do not set below 30)" } ], "disabledFeatures": { @@ -761,101 +796,150 @@ "label": "Cleanup stale Entra devices", "impact": "High Impact", "impactColour": "danger", + "addedDate": "2025-01-19", "powershellEquivalent": "Remove-MgDevice, Update-MgDevice or Graph API", "recommendedBy": [] }, { "name": "standards.UndoOauth", "cat": "Entra (AAD) Standards", - "tag": ["highimpact"], + "tag": [], "helpText": "Disables App consent and set to Allow user consent for apps", "addedComponent": [], "label": "Undo App Consent Standard", "impact": "High Impact", "impactColour": "danger", + "addedDate": "2022-01-07", "powershellEquivalent": "Update-MgPolicyAuthorizationPolicy", "recommendedBy": [] }, { "name": "standards.SecurityDefaults", "cat": "Entra (AAD) Standards", - "tag": ["highimpact"], + "tag": [], "helpText": "Enables security defaults for the tenant, for newer tenants this is enabled by default. Do not enable this feature if you use Conditional Access.", "docsDescription": "Enables SD for the tenant, which disables all forms of basic authentication and enforces users to configure MFA. Users are only prompted for MFA when a logon is considered 'suspect' by Microsoft.", "addedComponent": [], "label": "Enable Security Defaults", "impact": "High Impact", "impactColour": "danger", + "addedDate": "2021-11-19", "powershellEquivalent": "[Read more here](https://www.cyberdrain.com/automating-with-powershell-enabling-secure-defaults-and-sd-explained/)", "recommendedBy": [] }, { "name": "standards.DisableSMS", "cat": "Entra (AAD) Standards", - "tag": ["highimpact"], + "tag": [], "helpText": "This blocks users from using SMS as an MFA method. If a user only has SMS as a MFA method, they will be unable to log in.", "docsDescription": "Disables SMS as an MFA method for the tenant. If a user only has SMS as a MFA method, they will be unable to sign in.", "addedComponent": [], "label": "Disables SMS as an MFA method", "impact": "High Impact", "impactColour": "danger", + "addedDate": "2023-12-18", "powershellEquivalent": "Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration", - "recommendedBy": [] + "recommendedBy": ["CIPP"] }, { "name": "standards.DisableVoice", "cat": "Entra (AAD) Standards", - "tag": ["highimpact"], + "tag": [], "helpText": "This blocks users from using Voice call as an MFA method. If a user only has Voice as a MFA method, they will be unable to log in.", "docsDescription": "Disables Voice call as an MFA method for the tenant. If a user only has Voice call as a MFA method, they will be unable to sign in.", "addedComponent": [], "label": "Disables Voice call as an MFA method", "impact": "High Impact", "impactColour": "danger", + "addedDate": "2023-12-18", "powershellEquivalent": "Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration", - "recommendedBy": [] + "recommendedBy": ["CIPP"] }, { "name": "standards.DisableEmail", "cat": "Entra (AAD) Standards", - "tag": ["highimpact"], + "tag": [], "helpText": "This blocks users from using email as an MFA method. This disables the email OTP option for guest users, and instead prompts them to create a Microsoft account.", "addedComponent": [], "label": "Disables Email as an MFA method", "impact": "High Impact", "impactColour": "danger", + "addedDate": "2023-12-18", "powershellEquivalent": "Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration", "recommendedBy": [] }, { "name": "standards.Disablex509Certificate", "cat": "Entra (AAD) Standards", - "tag": ["highimpact"], + "tag": [], "helpText": "This blocks users from using Certificates as an MFA method.", "docsDescription": "", "addedComponent": [], "label": "Disables Certificates as an MFA method", "impact": "High Impact", "impactColour": "danger", + "addedDate": "2023-12-18", + "powershellEquivalent": "Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration", + "recommendedBy": [] + }, + { + "name": "standards.DisableQRCodePin", + "cat": "Entra (AAD) Standards", + "tag": [], + "helpText": "This blocks users from using QR Code Pin as an MFA method. If a user only has QR Code Pin as a MFA method, they will be unable to log in.", + "docsDescription": "Disables QR Code Pin as an MFA method for the tenant. If a user only has QR Code Pin as a MFA method, they will be unable to sign in.", + "addedComponent": [], + "label": "Disables QR Code Pin as an MFA method", + "impact": "High Impact", + "impactColour": "danger", + "addedDate": "2024-02-10", "powershellEquivalent": "Update-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration", "recommendedBy": [] }, { "name": "standards.PerUserMFA", "cat": "Entra (AAD) Standards", - "tag": ["highimpact"], + "tag": [], "helpText": "Enables per user MFA for all users.", "addedComponent": [], "label": "Enables per user MFA for all users.", "impact": "High Impact", "impactColour": "danger", + "addedDate": "2024-06-14", "powershellEquivalent": "Graph API", "recommendedBy": [] }, + { + "name": "standards.UserPreferredLanguage", + "cat": "Entra (AAD) Standards", + "tag": [], + "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.", + "addedComponent": [ + { + "type": "autoComplete", + "multiple": false, + "creatable": false, + "name": "standards.UserPreferredLanguage.preferredLanguage", + "label": "Preferred Language", + "api": { + "url": "/languageList.json", + "labelField": "language", + "valueField": "tag" + } + } + ], + "label": "Preferred language for all users", + "impact": "High Impact", + "impactColour": "info", + "addedDate": "2025-02-26", + "powershellEquivalent": "Update-MgUser -UserId user@domain.com -BodyParameter @{preferredLanguage='en-US'}", + "recommendedBy": [] + }, { "name": "standards.OutBoundSpamAlert", "cat": "Exchange Standards", - "tag": ["lowimpact", "CIS"], + "tag": ["CIS"], "helpText": "Set the Outbound Spam Alert e-mail address", "docsDescription": "Sets the e-mail address to which outbound spam alerts are sent.", "addedComponent": [ @@ -868,31 +952,33 @@ "label": "Set Outbound Spam Alert e-mail", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2023-05-03", "powershellEquivalent": "Set-HostedOutboundSpamFilterPolicy", "recommendedBy": ["CIS"] }, { "name": "standards.MessageExpiration", "cat": "Exchange Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Sets the transport message configuration to timeout a message at 12 hours.", "docsDescription": "Expires messages in the transport queue after 12 hours. Makes the NDR for failed messages show up faster for users. Default is 24 hours.", "addedComponent": [], "label": "Lower Transport Message Expiration to 12 hours", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-02-23", "powershellEquivalent": "Set-TransportConfig -MessageExpirationTimeout 12.00:00:00", "recommendedBy": [] }, { "name": "standards.GlobalQuarantineNotifications", "cat": "Exchange Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Sets the Global Quarantine Notification Interval to the selected value. Determines how often the quarantine notification is sent to users.", "docsDescription": "Sets the global quarantine notification interval for the tenant. This is the time between the quarantine notification emails are sent out to users. Default is 24 hours.", "addedComponent": [ { - "type": "select", + "type": "autoComplete", "multiple": false, "label": "Select value", "name": "standards.GlobalQuarantineNotifications.NotificationInterval", @@ -915,31 +1001,33 @@ "label": "Set Global Quarantine Notification Interval", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-05-03", "powershellEquivalent": "Set-QuarantinePolicy -EndUserSpamNotificationFrequency", "recommendedBy": [] }, { "name": "standards.DisableTNEF", "cat": "Exchange Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Disables Transport Neutral Encapsulation Format (TNEF)/winmail.dat for the tenant. TNEF can cause issues if the recipient is not using a client supporting TNEF.", "docsDescription": "Disables Transport Neutral Encapsulation Format (TNEF)/winmail.dat for the tenant. TNEF can cause issues if the recipient is not using a client supporting TNEF. Cannot be overridden by the user. For more information, see [Microsoft's documentation.](https://learn.microsoft.com/en-us/exchange/mail-flow/content-conversion/tnef-conversion?view=exchserver-2019)", "addedComponent": [], "label": "Disable TNEF/winmail.dat", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-04-26", "powershellEquivalent": "Set-RemoteDomain -Identity 'Default' -TNEFEnabled $false", - "recommendedBy": [] + "recommendedBy": ["CIPP"] }, { "name": "standards.FocusedInbox", "cat": "Exchange Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Sets the default Focused Inbox state for the tenant. This can be overridden by the user.", "docsDescription": "Sets the default Focused Inbox state for the tenant. This can be overridden by the user in their Outlook settings. For more information, see [Microsoft's documentation.](https://support.microsoft.com/en-us/office/focused-inbox-for-outlook-f445ad7f-02f4-4294-a82e-71d8964e3978)", "addedComponent": [ { - "type": "select", + "type": "autoComplete", "multiple": false, "label": "Select value", "name": "standards.FocusedInbox.state", @@ -958,18 +1046,19 @@ "label": "Set Focused Inbox state", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-04-26", "powershellEquivalent": "Set-OrganizationConfig -FocusedInboxOn $true or $false", "recommendedBy": [] }, { "name": "standards.CloudMessageRecall", "cat": "Exchange Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Sets the Cloud Message Recall state for the tenant. This allows users to recall messages from the cloud.", "docsDescription": "Sets the default state for Cloud Message Recall for the tenant. By default this is enabled. You can read more about the feature [here.](https://techcommunity.microsoft.com/t5/exchange-team-blog/cloud-based-message-recall-in-exchange-online/ba-p/3744714)", "addedComponent": [ { - "type": "select", + "type": "autoComplete", "multiple": false, "label": "Select value", "name": "standards.CloudMessageRecall.state", @@ -988,55 +1077,66 @@ "label": "Set Cloud Message Recall state", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-05-31", "powershellEquivalent": "Set-OrganizationConfig -MessageRecallEnabled", "recommendedBy": [] }, { "name": "standards.AutoExpandArchive", "cat": "Exchange Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Enables auto-expanding archives for the tenant", "docsDescription": "Enables auto-expanding archives for the tenant. Does not enable archives for users.", "addedComponent": [], "label": "Enable Auto-expanding archives", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2021-11-16", "powershellEquivalent": "Set-OrganizationConfig -AutoExpandingArchive", "recommendedBy": [] }, { "name": "standards.EnableOnlineArchiving", "cat": "Exchange Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Enables the In-Place Online Archive for all UserMailboxes with a valid license.", "addedComponent": [], "label": "Enable Online Archive for all users", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-01-20", "powershellEquivalent": "Enable-Mailbox -Archive $true", "recommendedBy": [] }, { "name": "standards.EnableLitigationHold", "cat": "Exchange Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Enables litigation hold for all UserMailboxes with a valid license.", - "addedComponent": [], + "addedComponent": [ + { + "type": "textField", + "name": "standards.EnableLitigationHold.days", + "required": false, + "label": "Days to apply for litigation hold" + } + ], "label": "Enable Litigation Hold for all users", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-06-25", "powershellEquivalent": "Set-Mailbox -LitigationHoldEnabled $true", "recommendedBy": [] }, { "name": "standards.SpoofWarn", "cat": "Exchange Standards", - "tag": ["lowimpact", "CIS"], + "tag": ["CIS"], "helpText": "Adds or removes indicators to e-mail messages received from external senders in Outlook. Works on all Outlook clients/OWA", "docsDescription": "Adds or removes indicators to e-mail messages received from external senders in Outlook. You can read more about this feature on [Microsoft's Exchange Team Blog.](https://techcommunity.microsoft.com/t5/exchange-team-blog/native-external-sender-callouts-on-email-in-outlook/ba-p/2250098)", "addedComponent": [ { - "type": "select", + "type": "autoComplete", "multiple": false, "label": "Select value", "name": "standards.SpoofWarn.state", @@ -1050,18 +1150,27 @@ "value": "disabled" } ] + }, + { + "type": "autoComplete", + "multiple": true, + "creatable": true, + "required": false, + "label": "Enter allowed senders(domain.com, *.domain.com or test@domain.com)", + "name": "standards.SpoofWarn.AllowListAdd" } ], "label": "Enable or disable 'external' warning in Outlook", "impact": "Low Impact", "impactColour": "info", - "powershellEquivalent": "et-ExternalInOutlook \u2013Enabled $true or $false", - "recommendedBy": ["CIS"] + "addedDate": "2021-11-16", + "powershellEquivalent": "Set-ExternalInOutlook \u2013Enabled $true or $false", + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.EnableMailTips", "cat": "Exchange Standards", - "tag": ["lowimpact", "CIS", "exo_mailtipsenabled"], + "tag": ["CIS", "exo_mailtipsenabled"], "helpText": "Enables all MailTips in Outlook. MailTips are the notifications Outlook and Outlook on the web shows when an email you create, meets some requirements", "addedComponent": [ { @@ -1069,24 +1178,26 @@ "name": "standards.EnableMailTips.MailTipsLargeAudienceThreshold", "label": "Number of recipients to trigger the large audience MailTip (Default is 25)", "placeholder": "Enter a profile name", - "default": 25 + "defaultValue": 25 } ], "label": "Enable all MailTips", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-01-14", "powershellEquivalent": "Set-OrganizationConfig", - "recommendedBy": ["CIS"] + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.TeamsMeetingsByDefault", "cat": "Exchange Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Sets the default state for automatically turning meetings into Teams meetings for the tenant. This can be overridden by the user in Outlook.", "addedComponent": [ { - "type": "select", + "type": "autoComplete", "multiple": false, + "creatable": false, "label": "Select value", "name": "standards.TeamsMeetingsByDefault.state", "options": [ @@ -1104,88 +1215,94 @@ "label": "Set Teams Meetings by default state", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-05-31", "powershellEquivalent": "Set-OrganizationConfig -OnlineMeetingsByDefaultEnabled", "recommendedBy": [] }, { "name": "standards.DisableViva", "cat": "Exchange Standards", - "tag": ["lowimpact"], - "helpText": "Disables the daily viva reports for all users.", + "tag": [], + "helpText": "Disables the daily viva reports for all users. This standard requires the CIPP-SAM application to have the Company Administrator (Global Admin) role in the tenant. Enable this using CIPP > Advanced > Super Admin > SAM App Roles. Activate the roles with a CPV refresh.", "docsDescription": "", "addedComponent": [], "label": "Disable daily Insight/Viva reports", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2022-05-25", "powershellEquivalent": "Set-UserBriefingConfig", "recommendedBy": [] }, { "name": "standards.RotateDKIM", "cat": "Exchange Standards", - "tag": ["lowimpact", "CIS"], + "tag": ["CIS"], "helpText": "Rotate DKIM keys that are 1024 bit to 2048 bit", "addedComponent": [], "label": "Rotate DKIM keys that are 1024 bit to 2048 bit", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2023-03-14", "powershellEquivalent": "Rotate-DkimSigningConfig", - "recommendedBy": ["CIS"] + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.AddDKIM", "cat": "Exchange Standards", - "tag": ["lowimpact", "CIS"], + "tag": ["CIS"], "helpText": "Enables DKIM for all domains that currently support it", "addedComponent": [], "label": "Enables DKIM for all domains that currently support it", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2023-03-14", "powershellEquivalent": "New-DkimSigningConfig and Set-DkimSigningConfig", - "recommendedBy": ["CIS"] + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.EnableMailboxAuditing", "cat": "Exchange Standards", - "tag": ["lowimpact", "CIS", "exo_mailboxaudit"], + "tag": ["CIS", "exo_mailboxaudit"], "helpText": "Enables Mailbox auditing for all mailboxes and on tenant level. Disables audit bypass on all mailboxes. Unified Audit Log needs to be enabled for this standard to function.", "docsDescription": "Enables mailbox auditing on tenant level and for all mailboxes. Disables audit bypass on all mailboxes. By default Microsoft does not enable mailbox auditing for Resource Mailboxes, Public Folder Mailboxes and DiscoverySearch Mailboxes. Unified Audit Log needs to be enabled for this standard to function.", "addedComponent": [], "label": "Enable Mailbox auditing", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-01-08", "powershellEquivalent": "Set-OrganizationConfig -AuditDisabled $false", - "recommendedBy": ["CIS"] + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.SendReceiveLimitTenant", "cat": "Exchange Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Sets the Send and Receive limits for new users. Valid values are 1MB to 150MB", "addedComponent": [ { "type": "number", "name": "standards.SendReceiveLimitTenant.SendLimit", "label": "Send limit in MB (Default is 35)", - "default": 35 + "defaultValue": 35 }, { "type": "number", "name": "standards.SendReceiveLimitTenant.ReceiveLimit", "label": "Receive Limit in MB (Default is 36)", - "default": 36 + "defaultValue": 36 } ], "label": "Set send/receive size limits", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2023-11-16", "powershellEquivalent": "Set-MailboxPlan", "recommendedBy": [] }, { "name": "standards.calDefault", "cat": "Exchange Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Sets the default sharing level for the default calendar, for all users", "docsDescription": "Sets the default sharing level for the default calendar for all users in the tenant. You can read about the different sharing levels [here.](https://learn.microsoft.com/en-us/powershell/module/exchange/set-mailboxfolderpermission?view=exchange-ps#-accessrights)", "disabledFeatures": { @@ -1195,10 +1312,10 @@ }, "addedComponent": [ { - "type": "select", + "type": "autoComplete", "multiple": false, "label": "Select Sharing Level", - "name": "standards.calDefault.permissionlevel", + "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.", @@ -1250,55 +1367,85 @@ "label": "Set Sharing Level for Default calendar", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2023-04-27", "powershellEquivalent": "Set-MailboxFolderPermission", "recommendedBy": [] }, { "name": "standards.DisableExternalCalendarSharing", "cat": "Exchange Standards", - "tag": ["lowimpact", "CIS", "exo_individualsharing"], + "tag": ["CIS", "exo_individualsharing"], "helpText": "Disables the ability for users to share their calendar with external users. Only for the default policy, so exclusions can be made if needed.", "docsDescription": "Disables external calendar sharing for the entire tenant. This is not a widely used feature, and it's therefore unlikely that this will impact users. Only for the default policy, so exclusions can be made if needed by making a new policy and assigning it to users.", "addedComponent": [], "label": "Disable external calendar sharing", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-01-08", "powershellEquivalent": "Get-SharingPolicy | Set-SharingPolicy -Enabled $False", "recommendedBy": ["CIS"] }, { - "name": "standardsAutoAddProxy", + "name": "standards.AutoAddProxy", "cat": "Exchange Standards", - "tag": ["lowimpact", "CIS"], + "tag": ["CIS"], "helpText": "Automatically adds all available domains as a proxy address.", - "docsDescription": "Automatically finds all available domain names in the tenant, and tries to add proxyaddresses based on the users UPN to each of these.", + "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.", "addedComponent": [], "label": "Automatically deploy proxy addresses", "impact": "Medium Impact", "impactColour": "warning", - "powershellEquivalent": "set-mailbox -emailaddresses @{add=$emailaddress}" + "addedDate": "2025-02-07", + "powershellEquivalent": "Set-Mailbox -EmailAddresses @{add=$EmailAddress}", + "recommendedBy": [], + "disabledFeatures": { + "report": true, + "warn": true, + "remediate": false + } }, { "name": "standards.DisableAdditionalStorageProviders", "cat": "Exchange Standards", - "tag": ["lowimpact", "CIS", "exo_storageproviderrestricted"], + "tag": ["CIS", "exo_storageproviderrestricted"], "helpText": "Disables the ability for users to open files in Outlook on the Web, from other providers such as Box, Dropbox, Facebook, Google Drive, OneDrive Personal, etc.", "docsDescription": "Disables additional storage providers in OWA. This is to prevent users from using personal storage providers like Dropbox, Google Drive, etc. Usually this has little user impact.", "addedComponent": [], "label": "Disable additional storage providers in OWA", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-01-17", "powershellEquivalent": "Get-OwaMailboxPolicy | Set-OwaMailboxPolicy -AdditionalStorageProvidersEnabled $False", "recommendedBy": ["CIS"] }, + { + "name": "standards.AntiSpamSafeList", + "cat": "Defender Standards", + "tag": [], + "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.", + "addedComponent": [ + { + "type": "switch", + "name": "standards.AntiSpamSafeList.EnableSafeList", + "label": "Enable Safe List" + } + ], + "label": "Set Anti-Spam Connection Filter Safe List", + "impact": "Medium Impact", + "impactColour": "info", + "addedDate": "2025-02-15", + "powershellEquivalent": "Set-HostedConnectionFilterPolicy \"Default\" -EnableSafeList $true", + "recommendedBy": [] + }, { "name": "standards.ShortenMeetings", "cat": "Exchange Standards", - "tag": ["mediumimpact"], + "tag": [], "helpText": "Sets the shorten meetings settings on a tenant level. This will shorten meetings by the selected amount of minutes. Valid values are 0 to 29. Short meetings are under 60 minutes, long meetings are over 60 minutes.", "addedComponent": [ { - "type": "select", + "type": "autoComplete", "multiple": false, "label": "Select value", "name": "standards.ShortenMeetings.ShortenEventScopeDefault", @@ -1321,30 +1468,31 @@ "type": "number", "name": "standards.ShortenMeetings.DefaultMinutesToReduceShortEventsBy", "label": "Minutes to reduce short calendar events by (Default is 5)", - "default": 5 + "defaultValue": 5 }, { "type": "number", "name": "standards.ShortenMeetings.DefaultMinutesToReduceLongEventsBy", "label": "Minutes to reduce long calendar events by (Default is 10)", - "default": 10 + "defaultValue": 10 } ], "label": "Set shorten meetings state", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2024-05-27", "powershellEquivalent": "Set-OrganizationConfig -ShortenEventScopeDefault -DefaultMinutesToReduceShortEventsBy -DefaultMinutesToReduceLongEventsBy", "recommendedBy": [] }, { "name": "standards.Bookings", "cat": "Exchange Standards", - "tag": ["mediumimpact"], + "tag": [], "helpText": "Sets the state of Bookings on the tenant. Bookings is a scheduling tool that allows users to book appointments with others both internal and external.", "docsDescription": "", "addedComponent": [ { - "type": "select", + "type": "autoComplete", "multiple": false, "label": "Select value", "name": "standards.Bookings.state", @@ -1363,26 +1511,28 @@ "label": "Set Bookings state", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2024-05-31", "powershellEquivalent": "Set-OrganizationConfig -BookingsEnabled", "recommendedBy": [] }, { "name": "standards.DisableOutlookAddins", "cat": "Exchange Standards", - "tag": ["mediumimpact", "CIS", "exo_outlookaddins"], + "tag": ["CIS", "exo_outlookaddins"], "helpText": "Disables the ability for users to install add-ins in Outlook. This is to prevent users from installing malicious add-ins.", "docsDescription": "Disables users from being able to install add-ins in Outlook. Only admins are able to approve add-ins for the users. This is done to reduce the threat surface for data exfiltration.", "addedComponent": [], "label": "Disable users from installing add-ins in Outlook", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2024-02-05", "powershellEquivalent": "Get-ManagementRoleAssignment | Remove-ManagementRoleAssignment", "recommendedBy": ["CIS"] }, { "name": "standards.SafeSendersDisable", "cat": "Exchange Standards", - "tag": ["mediumimpact"], + "tag": [], "helpText": "Loops through all users and removes the Safe Senders list. This is to prevent SPF bypass attacks, as the Safe Senders list is not checked by SPF.", "addedComponent": [], "disabledFeatures": { @@ -1393,13 +1543,14 @@ "label": "Remove Safe Senders to prevent SPF bypass", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2023-10-26", "powershellEquivalent": "Set-MailboxJunkEmailConfiguration", - "recommendedBy": [] + "recommendedBy": ["CIPP"] }, { "name": "standards.DelegateSentItems", "cat": "Exchange Standards", - "tag": ["mediumimpact"], + "tag": [], "helpText": "Sets emails sent as and on behalf of shared mailboxes to also be stored in the shared mailbox sent items folder", "docsDescription": "This makes sure that e-mails sent from shared mailboxes or delegate mailboxes, end up in the mailbox of the shared/delegate mailbox instead of the sender, allowing you to keep replies in the same mailbox as the original e-mail.", "addedComponent": [ @@ -1412,31 +1563,33 @@ "label": "Set mailbox Sent Items delegation (Sent items for shared mailboxes)", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2021-11-16", "powershellEquivalent": "Set-Mailbox", "recommendedBy": [] }, { "name": "standards.SendFromAlias", "cat": "Exchange Standards", - "tag": ["mediumimpact"], + "tag": [], "helpText": "Enables the ability for users to send from their alias addresses.", "docsDescription": "Allows users to change the 'from' address to any set in their Azure AD Profile.", "addedComponent": [], "label": "Allow users to send from their alias addresses", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2022-05-25", "powershellEquivalent": "Set-Mailbox", - "recommendedBy": [] + "recommendedBy": ["CIPP"] }, { "name": "standards.UserSubmissions", "cat": "Exchange Standards", - "tag": ["mediumimpact"], + "tag": [], "helpText": "Set the state of the spam submission button in Outlook", "docsDescription": "Set the state of the built-in Report button in Outlook. This gives the users the ability to report emails as spam or phish.", "addedComponent": [ { - "type": "select", + "type": "autoComplete", "multiple": false, "label": "Select value", "name": "standards.UserSubmissions.state", @@ -1461,44 +1614,42 @@ "label": "Set the state of the built-in Report button in Outlook", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2024-06-28", "powershellEquivalent": "New-ReportSubmissionPolicy or Set-ReportSubmissionPolicy and New-ReportSubmissionRule or Set-ReportSubmissionRule", "recommendedBy": [] }, { "name": "standards.DisableSharedMailbox", "cat": "Exchange Standards", - "tag": ["mediumimpact", "CIS"], + "tag": ["CIS"], "helpText": "Blocks login for all accounts that are marked as a shared mailbox. This is Microsoft best practice to prevent direct logons to shared mailboxes.", "docsDescription": "Shared mailboxes can be directly logged into if the password is reset, this presents a security risk as do all shared login credentials. Microsoft's recommendation is to disable the user account for shared mailboxes. It would be a good idea to review the sign-in reports to establish potential impact.", "addedComponent": [], "label": "Disable Shared Mailbox AAD accounts", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2021-11-16", "powershellEquivalent": "Get-Mailbox & Update-MgUser", - "recommendedBy": ["CIS"] + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.EXODisableAutoForwarding", "cat": "Exchange Standards", - "tag": [ - "highimpact", - "CIS", - "mdo_autoforwardingmode", - "mdo_blockmailforward" - ], + "tag": ["CIS", "mdo_autoforwardingmode", "mdo_blockmailforward"], "helpText": "Disables the ability for users to automatically forward e-mails to external recipients.", "docsDescription": "Disables the ability for users to automatically forward e-mails to external recipients. This is to prevent data exfiltration. Please check if there are any legitimate use cases for this feature before implementing, like forwarding invoices and such.", "addedComponent": [], "label": "Disable automatic forwarding to external recipients", "impact": "High Impact", "impactColour": "danger", + "addedDate": "2024-07-26", "powershellEquivalent": "Set-HostedOutboundSpamFilterPolicy -AutoForwardingMode 'Off'", - "recommendedBy": ["CIS"] + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.RetentionPolicyTag", "cat": "Exchange Standards", - "tag": ["highimpact"], + "tag": [], "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.", "addedComponent": [ @@ -1512,13 +1663,14 @@ "label": "Retention Policy, permanently delete items in Deleted Items after X days", "impact": "High Impact", "impactColour": "danger", + "addedDate": "2025-02-02", "powershellEquivalent": "Set-RetentionPolicyTag", "recommendedBy": [] }, { "name": "standards.QuarantineRequestAlert", "cat": "Defender Standards", - "tag": ["lowimpact"], + "tag": [], "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.", "addedComponent": [ @@ -1531,19 +1683,50 @@ "label": "Quarantine Release Request Alert", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-07-15", "powershellEquivalent": "New-ProtectionAlert and Set-ProtectionAlert", "recommendedBy": [] }, { - "name": "standards.SafeLinksPolicy", + "name": "standards.SharePointMassDeletionAlert", "cat": "Defender Standards", - "tag": [ - "lowimpact", - "CIS", - "mdo_safelinksforemail", - "mdo_safelinksforOfficeApps" + "tag": [], + "helpText": "Sets a e-mail address to alert when a User deletes more than 20 SharePoint files within 60 minutes. NB: Requires a Office 365 E5 subscription, Office 365 E3 with Threat Intelligence or Office 365 EquivioAnalytics add-on.", + "docsDescription": "Sets a e-mail address to alert when a User deletes more than 20 SharePoint files within 60 minutes. This is useful for monitoring and ensuring that the correct SharePoint files are deleted. NB: Requires a Office 365 E5 subscription, Office 365 E3 with Threat Intelligence or Office 365 EquivioAnalytics add-on.", + "addedComponent": [ + { + "type": "number", + "name": "standards.SharePointMassDeletionAlert.Threshold", + "label": "Max files to delete within the time frame", + "defaultValue": 20 + }, + { + "type": "number", + "name": "standards.SharePointMassDeletionAlert.TimeWindow", + "label": "Time frame in minutes", + "defaultValue": 60 + }, + { + "type": "autoComplete", + "multiple": true, + "creatable": true, + "required": true, + "name": "standards.SharePointMassDeletionAlert.NotifyUser", + "label": "E-mail to receive the alert" + } ], - "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", + "label": "SharePoint Mass Deletion Alert", + "impact": "Low Impact", + "impactColour": "info", + "addedDate": "2025-04-07", + "powershellEquivalent": "New-ProtectionAlert and Set-ProtectionAlert", + "recommendedBy": [] + }, + { + "name": "standards.SafeLinksPolicy", + "cat": "Defender Standards", + "tag": ["CIS", "mdo_safelinksforemail", "mdo_safelinksforOfficeApps"], + "helpText": "This creates a Safe Links policy that automatically scans, tracks, and and enables safe links for Email, Office, and Teams for both external and internal senders", "addedComponent": [ { "type": "switch", @@ -1559,11 +1742,20 @@ "type": "switch", "label": "EnableOrganizationBranding", "name": "standards.SafeLinksPolicy.EnableOrganizationBranding" + }, + { + "type": "autoComplete", + "multiple": true, + "creatable": true, + "required": false, + "name": "standards.SafeLinksPolicy.DoNotRewriteUrls", + "label": "Do not rewrite the following URLs in email" } ], - "label": "Default SafeLinks Policy", + "label": "Default Safe Links Policy", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-03-25", "powershellEquivalent": "Set-SafeLinksPolicy or New-SafeLinksPolicy", "recommendedBy": ["CIS"] }, @@ -1571,7 +1763,6 @@ "name": "standards.AntiPhishPolicy", "cat": "Defender Standards", "tag": [ - "lowimpact", "CIS", "mdo_safeattachments", "mdo_highconfidencespamaction", @@ -1581,37 +1772,37 @@ "mdo_antiphishingpolicies", "mdo_phishthresholdlevel" ], - "helpText": "This creates a Anti-Phishing policy that automatically enables Mailbox Intelligence and spoofing, optional switches for Mailtips.", + "helpText": "This creates a Anti-Phishing policy that automatically enables Mailbox Intelligence and spoofing, optional switches for Mail tips.", "addedComponent": [ { "type": "number", "label": "Phishing email threshold. (Default 1)", "name": "standards.AntiPhishPolicy.PhishThresholdLevel", - "default": 1 + "defaultValue": 1 }, { "type": "switch", "label": "Show first contact safety tip", "name": "standards.AntiPhishPolicy.EnableFirstContactSafetyTips", - "default": true + "defaultValue": true }, { "type": "switch", "label": "Show user impersonation safety tip", "name": "standards.AntiPhishPolicy.EnableSimilarUsersSafetyTips", - "default": true + "defaultValue": true }, { "type": "switch", "label": "Show domain impersonation safety tip", "name": "standards.AntiPhishPolicy.EnableSimilarDomainsSafetyTips", - "default": true + "defaultValue": true }, { "type": "switch", "label": "Show user impersonation unusual characters safety tip", "name": "standards.AntiPhishPolicy.EnableUnusualCharactersSafetyTips", - "default": true + "defaultValue": true }, { "type": "select", @@ -1773,19 +1964,14 @@ "label": "Default Anti-Phishing Policy", "impact": "Low Impact", "impactColour": "info", - "powershellEquivalent": "Set-AntiphishPolicy or New-AntiphishPolicy", + "addedDate": "2024-03-25", + "powershellEquivalent": "Set-AntiPhishPolicy or New-AntiPhishPolicy", "recommendedBy": ["CIS"] }, { "name": "standards.SafeAttachmentPolicy", "cat": "Defender Standards", - "tag": [ - "lowimpact", - "CIS", - "mdo_safedocuments", - "mdo_commonattachmentsfilter", - "mdo_safeattachmentpolicy" - ], + "tag": ["CIS", "mdo_safedocuments", "mdo_commonattachmentsfilter", "mdo_safeattachmentpolicy"], "helpText": "This creates a Safe Attachment policy", "addedComponent": [ { @@ -1843,39 +2029,73 @@ "label": "Default Safe Attachment Policy", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-03-25", "powershellEquivalent": "Set-SafeAttachmentPolicy or New-SafeAttachmentPolicy", "recommendedBy": ["CIS"] }, { "name": "standards.AtpPolicyForO365", "cat": "Defender Standards", - "tag": ["lowimpact", "CIS"], + "tag": ["CIS"], "helpText": "This creates a Atp policy that enables Defender for Office 365 for SharePoint, OneDrive and Microsoft Teams.", "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, + "defaultValue": false, "required": false } ], "label": "Default Atp Policy For O365", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-03-25", "powershellEquivalent": "Set-AtpPolicyForO365", "recommendedBy": ["CIS"] }, { - "name": "standards.MalwareFilterPolicy", + "name": "standards.PhishingSimulations", "cat": "Defender Standards", - "tag": [ - "lowimpact", - "CIS", - "mdo_zapspam", - "mdo_zapphish", - "mdo_zapmalware" + "tag": [], + "helpText": "This creates a phishing simulation policy that enables phishing simulations for the entire tenant.", + "addedComponent": [ + { + "type": "autoComplete", + "multiple": true, + "creatable": true, + "required": true, + "label": "Phishing Simulation Domains", + "name": "standards.PhishingSimulations.Domains" + }, + { + "type": "autoComplete", + "multiple": true, + "creatable": true, + "required": true, + "label": "Phishing Simulation Sender IP Ranges", + "name": "standards.PhishingSimulations.SenderIpRanges" + }, + { + "type": "autoComplete", + "multiple": true, + "creatable": true, + "required": false, + "label": "Phishing Simulation Urls", + "name": "standards.PhishingSimulations.PhishingSimUrls" + } ], + "label": "Phishing Simulation Configuration", + "impact": "Medium Impact", + "impactColour": "info", + "addedDate": "2025-03-27", + "powershellEquivalent": "New-TenantAllowBlockListItems, New-PhishSimOverridePolicy and New-ExoPhishSimOverrideRule", + "recommendedBy": [] + }, + { + "name": "standards.MalwareFilterPolicy", + "cat": "Defender Standards", + "tag": ["CIS", "mdo_zapspam", "mdo_zapphish", "mdo_zapmalware"], "helpText": "This creates a Malware filter policy that enables the default File filter and Zero-hour auto purge for malware.", "addedComponent": [ { @@ -1948,20 +2168,43 @@ "label": "Default Malware Filter Policy", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-03-25", "powershellEquivalent": "Set-MalwareFilterPolicy or New-MalwareFilterPolicy", "recommendedBy": ["CIS"] }, + { + "name": "standards.PhishSimSpoofIntelligence", + "cat": "Defender Standards", + "tag": [], + "helpText": "This adds allowed domains to the Spoof Intelligence Allow/Block List.", + "addedComponent": [ + { + "type": "autoComplete", + "multiple": true, + "creatable": true, + "required": false, + "label": "Allowed Domains", + "name": "standards.PhishSimSpoofIntelligence.AllowedDomains" + } + ], + "label": "Add allowed domains to Spoof Intelligence", + "impact": "Medium Impact", + "impactColour": "info", + "addedDate": "2025-03-28", + "powershellEquivalent": "New-TenantAllowBlockListSpoofItems", + "recommendedBy": [] + }, { "name": "standards.SpamFilterPolicy", "cat": "Defender Standards", - "tag": ["mediumimpact"], + "tag": [], "helpText": "This standard creates a Spam filter policy similar to the default strict policy.", "addedComponent": [ { "type": "number", "label": "Bulk email threshold (Default 7)", "name": "standards.SpamFilterPolicy.BulkThreshold", - "default": 7 + "defaultValue": 7 }, { "type": "autoComplete", @@ -2144,18 +2387,103 @@ "value": "DefaultFullAccessWithNotificationPolicy" } ] + }, + { + "type": "switch", + "name": "standards.SpamFilterPolicy.IncreaseScoreWithImageLinks", + "label": "Increase score if message contains image links to remote websites", + "defaultValue": false + }, + { + "type": "switch", + "name": "standards.SpamFilterPolicy.IncreaseScoreWithBizOrInfoUrls", + "label": "Increase score if message contains links to .biz or .info domains", + "defaultValue": false + }, + { + "type": "switch", + "name": "standards.SpamFilterPolicy.MarkAsSpamFramesInHtml", + "label": "Mark as spam if message contains HTML or iframe tags", + "defaultValue": false + }, + { + "type": "switch", + "name": "standards.SpamFilterPolicy.MarkAsSpamObjectTagsInHtml", + "label": "Mark as spam if message contains HTML object tags", + "defaultValue": false + }, + { + "type": "switch", + "name": "standards.SpamFilterPolicy.MarkAsSpamEmbedTagsInHtml", + "label": "Mark as spam if message contains HTML embed tags", + "defaultValue": false + }, + { + "type": "switch", + "name": "standards.SpamFilterPolicy.MarkAsSpamFormTagsInHtml", + "label": "Mark as spam if message contains HTML form tags", + "defaultValue": false + }, + { + "type": "switch", + "name": "standards.SpamFilterPolicy.MarkAsSpamWebBugsInHtml", + "label": "Mark as spam if message contains web bugs (also known as web beacons)", + "defaultValue": false + }, + { + "type": "switch", + "name": "standards.SpamFilterPolicy.MarkAsSpamSensitiveWordList", + "label": "Mark as spam if message contains words from the sensitive words list", + "defaultValue": false + }, + { + "type": "switch", + "name": "standards.SpamFilterPolicy.EnableLanguageBlockList", + "label": "Enable language block list", + "defaultValue": false + }, + { + "type": "autoComplete", + "multiple": true, + "creatable": true, + "required": false, + "name": "standards.SpamFilterPolicy.LanguageBlockList", + "label": "Languages to block (uppercase ISO 639-1 two-letter)" + }, + { + "type": "switch", + "name": "standards.SpamFilterPolicy.EnableRegionBlockList", + "label": "Enable region block list", + "defaultValue": false + }, + { + "type": "autoComplete", + "multiple": true, + "creatable": true, + "required": false, + "name": "standards.SpamFilterPolicy.RegionBlockList", + "label": "Regions to block (uppercase ISO 3166-1 two-letter)" + }, + { + "type": "autoComplete", + "multiple": true, + "creatable": true, + "required": false, + "name": "standards.SpamFilterPolicy.AllowedSenderDomains", + "label": "Allowed sender domains" } ], "label": "Default Spam Filter Policy", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2024-07-15", "powershellEquivalent": "New-HostedContentFilterPolicy or Set-HostedContentFilterPolicy", "recommendedBy": [] }, { "name": "standards.intuneDeviceRetirementDays", "cat": "Intune Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "A value between 0 and 270 is supported. A value of 0 disables retirement, retired devices are removed from Intune after the specified number of days.", "addedComponent": [ { @@ -2167,13 +2495,14 @@ "label": "Set inactive device retirement days", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2023-05-19", "powershellEquivalent": "Graph API", - "recommendedBy": [] + "recommendedBy": ["CIPP"] }, { "name": "standards.intuneBrandingProfile", "cat": "Intune Standards", - "tag": ["lowimpact"], + "tag": [], "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.", "addedComponent": [ { @@ -2239,13 +2568,14 @@ "label": "Set Intune Company Portal branding profile", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-06-20", "powershellEquivalent": "Graph API", "recommendedBy": [] }, { "name": "standards.IntuneComplianceSettings", "cat": "Intune Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Sets the mark devices with no compliance policy assigned as compliance/non compliant and Compliance status validity period.", "addedComponent": [ { @@ -2275,47 +2605,156 @@ "label": "Set Intune Compliance Settings", "impact": "Low Impact", "impactColour": "info", - "powershellEquivalent": "", + "addedDate": "2024-11-12", + "powershellEquivalent": "Graph API", + "recommendedBy": [] + }, + { + "name": "standards.MDMScope", + "cat": "Intune Standards", + "tag": [], + "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.", + "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 + } + ], + "label": "Configure MDM user scope", + "impact": "Low Impact", + "impactColour": "info", + "addedDate": "2025-02-18", + "powershellEquivalent": "Graph API", + "recommendedBy": [] + }, + { + "name": "standards.DefaultPlatformRestrictions", + "cat": "Intune Standards", + "tag": [], + "helpText": "Sets the default platform restrictions for enrolling devices into Intune. Note: Do not block personally owned if platform is blocked.", + "addedComponent": [ + { + "type": "switch", + "name": "standards.DefaultPlatformRestrictions.platformAndroidForWorkBlocked", + "label": "Block platform Android Enterprise (work profile)", + "default": false + }, + { + "type": "switch", + "name": "standards.DefaultPlatformRestrictions.personalAndroidForWorkBlocked", + "label": "Block personally owned Android Enterprise (work profile)", + "default": false + }, + { + "type": "switch", + "name": "standards.DefaultPlatformRestrictions.platformAndroidBlocked", + "label": "Block platform Android", + "default": false + }, + { + "type": "switch", + "name": "standards.DefaultPlatformRestrictions.personalAndroidBlocked", + "label": "Block personally owned Android", + "default": false + }, + { + "type": "switch", + "name": "standards.DefaultPlatformRestrictions.platformiOSBlocked", + "label": "Block platform iOS", + "default": false + }, + { + "type": "switch", + "name": "standards.DefaultPlatformRestrictions.personaliOSBlocked", + "label": "Block personally owned iOS", + "default": false + }, + { + "type": "switch", + "name": "standards.DefaultPlatformRestrictions.platformMacOSBlocked", + "label": "Block platform macOS", + "default": false + }, + { + "type": "switch", + "name": "standards.DefaultPlatformRestrictions.personalMacOSBlocked", + "label": "Block personally owned macOS", + "default": false + }, + { + "type": "switch", + "name": "standards.DefaultPlatformRestrictions.platformWindowsBlocked", + "label": "Block platform Windows", + "default": false + }, + { + "type": "switch", + "name": "standards.DefaultPlatformRestrictions.personalWindowsBlocked", + "label": "Block personally owned Windows", + "default": false + } + ], + "label": "Device enrollment restrictions", + "impact": "Low Impact", + "impactColour": "info", + "addedDate": "2025-04-01", + "powershellEquivalent": "Graph API", "recommendedBy": [] }, { "name": "standards.intuneDeviceReg", "cat": "Intune Standards", - "tag": ["mediumimpact"], - "helpText": "sets the maximum number of devices that can be registered by a user. A value of 0 disables device registration by users", + "tag": [], + "helpText": "Sets the maximum number of devices that can be registered by a user. A value of 0 disables device registration by users", "addedComponent": [ { "type": "number", "name": "standards.intuneDeviceReg.max", - "label": "Maximum devices (Enter 2147483647 for unlimited.)" + "label": "Maximum devices (Enter 2147483647 for unlimited.)", + "required": true } ], "label": "Set Maximum Number of Devices per user", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2023-03-27", "powershellEquivalent": "Update-MgBetaPolicyDeviceRegistrationPolicy", "recommendedBy": [] }, { "name": "standards.intuneRequireMFA", "cat": "Intune Standards", - "tag": ["mediumimpact"], + "tag": [], "helpText": "Requires MFA for all users to register devices with Intune. This is useful when not using Conditional Access.", - "label": "Require Multifactor Authentication to register or join devices with Microsoft Entra", + "label": "Require Multi-factor Authentication to register or join devices with Microsoft Entra", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2023-10-23", "powershellEquivalent": "Update-MgBetaPolicyDeviceRegistrationPolicy", "recommendedBy": [] }, { "name": "standards.DeletedUserRentention", "cat": "SharePoint Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Sets the retention period for deleted users OneDrive to the specified period of time. The default is 30 days.", "docsDescription": "When a OneDrive user gets deleted, the personal SharePoint site is saved for selected amount of time that data can be retrieved from it.", "addedComponent": [ { - "type": "select", + "type": "autoComplete", "multiple": false, "name": "standards.DeletedUserRentention.Days", "label": "Retention time (Default 30 days)", @@ -2374,13 +2813,14 @@ "label": "Set deleted user retention time in OneDrive", "impact": "Low Impact", "impactColour": "info", - "powershellEquivalent": "Update-MgBetaAdminSharepointSetting", + "addedDate": "2022-06-15", + "powershellEquivalent": "Update-MgBetaAdminSharePointSetting", "recommendedBy": [] }, { "name": "standards.TenantDefaultTimezone", "cat": "SharePoint Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Sets the default timezone for the tenant. This will be used for all new users and sites.", "addedComponent": [ { @@ -2392,61 +2832,66 @@ "label": "Set Default Timezone for Tenant", "impact": "Low Impact", "impactColour": "info", - "powershellEquivalent": "Update-MgBetaAdminSharepointSetting", + "addedDate": "2024-04-20", + "powershellEquivalent": "Update-MgBetaAdminSharePointSetting", "recommendedBy": [] }, { "name": "standards.SPAzureB2B", "cat": "SharePoint Standards", - "tag": ["lowimpact", "CIS"], + "tag": ["CIS"], "helpText": "Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled", "addedComponent": [], "label": "Enable SharePoint and OneDrive integration with Azure AD B2B", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-07-09", "powershellEquivalent": "Set-SPOTenant -EnableAzureADB2BIntegration $true", - "recommendedBy": ["CIS 3.0"] + "recommendedBy": ["CIS"] }, { "name": "standards.SPDisallowInfectedFiles", "cat": "SharePoint Standards", - "tag": ["lowimpact", "CIS"], + "tag": ["CIS"], "helpText": "Ensure Office 365 SharePoint infected files are disallowed for download", "addedComponent": [], "label": "Disallow downloading infected files from SharePoint", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-07-09", "powershellEquivalent": "Set-SPOTenant -DisallowInfectedFileDownload $true", - "recommendedBy": ["CIS 3.0"] + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.SPDisableLegacyWorkflows", "cat": "SharePoint Standards", - "tag": ["lowimpact"], + "tag": [], "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.", "addedComponent": [], "label": "Disable Legacy Workflows", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-07-15", "powershellEquivalent": "Set-SPOTenant -DisableWorkflow2010 $true -DisableWorkflow2013 $true -DisableBackToClassic $true", "recommendedBy": [] }, { "name": "standards.SPDirectSharing", "cat": "SharePoint Standards", - "tag": ["mediumimpact", "CIS"], + "tag": ["CIS"], "helpText": "Ensure default link sharing is set to Direct in SharePoint and OneDrive", "addedComponent": [], "label": "Default sharing to Direct users", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2024-07-09", "powershellEquivalent": "Set-SPOTenant -DefaultSharingLinkType Direct", - "recommendedBy": ["CIS 3.0"] + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.SPExternalUserExpiration", "cat": "SharePoint Standards", - "tag": ["mediumimpact", "CIS"], + "tag": ["CIS"], "helpText": "Ensure guest access to a site or OneDrive will expire automatically", "addedComponent": [ { @@ -2458,31 +2903,33 @@ "label": "Set guest access to expire automatically", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2024-07-09", "powershellEquivalent": "Set-SPOTenant -ExternalUserExpireInDays 30 -ExternalUserExpirationRequired $True", - "recommendedBy": ["CIS 3.0"] + "recommendedBy": ["CIS"] }, { "name": "standards.SPEmailAttestation", "cat": "SharePoint Standards", - "tag": ["mediumimpact", "CIS"], - "helpText": "Ensure reauthentication with verification code is restricted", + "tag": ["CIS"], + "helpText": "Ensure re-authentication with verification code is restricted", "addedComponent": [ { "type": "number", "name": "standards.SPEmailAttestation.Days", - "label": "Require reauth every X Days (Default 15)" + "label": "Require re-authentication every X Days (Default 15)" } ], - "label": "Require reauthentication with verification code", + "label": "Require re-authentication with verification code", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2024-07-09", "powershellEquivalent": "Set-SPOTenant -EmailAttestationRequired $true -EmailAttestationReAuthDays 15", - "recommendedBy": ["CIS 3.0"] + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.DisableAddShortcutsToOneDrive", "cat": "SharePoint Standards", - "tag": ["mediumimpact"], + "tag": [], "helpText": "If disabled, the button Add shortcut to OneDrive will be removed and users in the tenant will no longer be able to add new shortcuts to their OneDrive. Existing shortcuts will remain functional", "addedComponent": [ { @@ -2506,13 +2953,14 @@ "label": "Set Add Shortcuts To OneDrive button state", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2023-07-25", "powershellEquivalent": "Set-SPOTenant -DisableAddShortcutsToOneDrive $true or $false", "recommendedBy": [] }, { "name": "standards.SPSyncButtonState", "cat": "SharePoint Standards", - "tag": ["mediumimpact"], + "tag": [], "helpText": "If disabled, users in the tenant will no longer be able to use the Sync button to sync SharePoint content on all sites. However, existing synced content will remain functional on the user's computer.", "addedComponent": [ { @@ -2536,30 +2984,32 @@ "label": "Set SharePoint sync button state", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2024-07-26", "powershellEquivalent": "Set-SPOTenant -HideSyncButtonOnTeamSite $true or $false", "recommendedBy": [] }, { "name": "standards.DisableSharePointLegacyAuth", "cat": "SharePoint Standards", - "tag": ["mediumimpact", "CIS", "spo_legacy_auth"], + "tag": ["CIS", "spo_legacy_auth"], "helpText": "Disables the ability to authenticate with SharePoint using legacy authentication methods. Any applications that use legacy authentication will need to be updated to use modern authentication.", "docsDescription": "Disables the ability for users and applications to access SharePoint via legacy basic authentication. This will likely not have any user impact, but will block systems/applications depending on basic auth or the SharePointOnlineCredentials class.", "addedComponent": [], "label": "Disable legacy basic authentication for SharePoint", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2024-02-05", "powershellEquivalent": "Set-SPOTenant -LegacyAuthProtocolsEnabled $false", - "recommendedBy": ["CIS"] + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.sharingCapability", "cat": "SharePoint Standards", - "tag": ["highimpact", "CIS"], + "tag": ["CIS"], "helpText": "Sets the default sharing level for OneDrive and SharePoint. This is a tenant wide setting and overrules any settings set on the site level", "addedComponent": [ { - "type": "select", + "type": "autoComplete", "multiple": false, "label": "Select Sharing Level", "name": "standards.sharingCapability.Level", @@ -2586,39 +3036,42 @@ "label": "Set Sharing Level for OneDrive and SharePoint", "impact": "High Impact", "impactColour": "danger", - "powershellEquivalent": "Update-MgBetaAdminSharepointSetting", - "recommendedBy": ["CIS"] + "addedDate": "2022-06-15", + "powershellEquivalent": "Update-MgBetaAdminSharePointSetting", + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.DisableReshare", "cat": "SharePoint Standards", - "tag": ["highimpact", "CIS"], + "tag": ["CIS"], "helpText": "Disables the ability for external users to share files they don't own. Sharing links can only be made for People with existing access", "docsDescription": "Disables the ability for external users to share files they don't own. Sharing links can only be made for People with existing access. This is a tenant wide setting and overrules any settings set on the site level", "addedComponent": [], - "label": "Disable Resharing by External Users", + "label": "Disable Re-sharing by External Users", "impact": "High Impact", "impactColour": "danger", - "powershellEquivalent": "Update-MgBetaAdminSharepointSetting", - "recommendedBy": ["CIS"] + "addedDate": "2022-06-15", + "powershellEquivalent": "Update-MgBetaAdminSharePointSetting", + "recommendedBy": ["CIS", "CIPP"] }, { "name": "standards.DisableUserSiteCreate", "cat": "SharePoint Standards", - "tag": ["highimpact"], + "tag": [], "helpText": "Disables users from creating new SharePoint sites", "docsDescription": "Disables standard users from creating SharePoint sites, also disables the ability to fully create teams", "addedComponent": [], "label": "Disable site creation by standard users", "impact": "High Impact", "impactColour": "danger", - "powershellEquivalent": "Update-MgAdminSharepointSetting", + "addedDate": "2022-06-15", + "powershellEquivalent": "Update-MgAdminSharePointSetting", "recommendedBy": [] }, { "name": "standards.ExcludedfileExt", "cat": "SharePoint Standards", - "tag": ["highimpact"], + "tag": [], "helpText": "Sets the file extensions that are excluded from syncing with OneDrive. These files will be blocked from upload. '*.' is automatically added to the extension and can be omitted.", "addedComponent": [ { @@ -2630,41 +3083,44 @@ "label": "Exclude File Extensions from Syncing", "impact": "High Impact", "impactColour": "danger", - "powershellEquivalent": "Update-MgAdminSharepointSetting", + "addedDate": "2022-06-15", + "powershellEquivalent": "Update-MgAdminSharePointSetting", "recommendedBy": [] }, { "name": "standards.disableMacSync", "cat": "SharePoint Standards", - "tag": ["highimpact"], + "tag": [], "helpText": "Disables the ability for Mac devices to sync with OneDrive.", "addedComponent": [], "label": "Do not allow Mac devices to sync using OneDrive", "impact": "High Impact", "impactColour": "danger", - "powershellEquivalent": "Update-MgAdminSharepointSetting", + "addedDate": "2022-06-15", + "powershellEquivalent": "Update-MgAdminSharePointSetting", "recommendedBy": [] }, { "name": "standards.unmanagedSync", "cat": "SharePoint Standards", - "tag": ["highimpact"], + "tag": [], "helpText": "The unmanaged Sync standard has been temporarily disabled and does nothing.", "addedComponent": [], "label": "Only allow users to sync OneDrive from AAD joined devices", "impact": "High Impact", "impactColour": "danger", - "powershellEquivalent": "Update-MgAdminSharepointSetting", + "addedDate": "2022-06-15", + "powershellEquivalent": "Update-MgAdminSharePointSetting", "recommendedBy": [] }, { "name": "standards.sharingDomainRestriction", "cat": "SharePoint Standards", - "tag": ["highimpact", "CIS"], + "tag": ["CIS"], "helpText": "Restricts sharing to only users with the specified domain. This is useful for organizations that only want to share with their own domain.", "addedComponent": [ { - "type": "select", + "type": "autoComplete", "multiple": false, "name": "standards.sharingDomainRestriction.Mode", "label": "Limit external sharing by domains", @@ -2693,13 +3149,14 @@ "label": "Restrict sharing to a specific domain", "impact": "High Impact", "impactColour": "danger", - "powershellEquivalent": "Update-MgAdminSharepointSetting", + "addedDate": "2024-06-20", + "powershellEquivalent": "Update-MgAdminSharePointSetting", "recommendedBy": [] }, { "name": "standards.TeamsGlobalMeetingPolicy", "cat": "Teams Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Defines the CIS recommended global meeting policy for Teams. This includes AllowAnonymousUsersToJoinMeeting, AllowAnonymousUsersToStartMeeting, AutoAdmittedUsers, AllowPSTNUsersToBypassLobby, MeetingChatEnabledType, DesignatedPresenterRoleMode, AllowExternalParticipantGiveRequestControl", "addedComponent": [ { @@ -2754,18 +3211,24 @@ "value": "Disabled" } ] + }, + { + "type": "switch", + "name": "standards.TeamsGlobalMeetingPolicy.AllowExternalParticipantGiveRequestControl", + "label": "External participants can give or request control" } ], "label": "Define Global Meeting Policy for Teams", "impact": "Low Impact", "impactColour": "info", + "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"] + "recommendedBy": ["CIS"] }, { "name": "standards.TeamsEmailIntegration", "cat": "Teams Standards", - "tag": ["lowimpact"], + "tag": [], "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.", "addedComponent": [ @@ -2778,13 +3241,14 @@ "label": "Disallow emails to be sent to channel email addresses", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-07-30", "powershellEquivalent": "Set-CsTeamsClientConfiguration -AllowEmailIntoChannel $false", - "recommendedBy": ["CIS 3.0"] + "recommendedBy": ["CIS"] }, { "name": "standards.TeamsExternalFileSharing", "cat": "Teams Standards", - "tag": ["lowimpact"], + "tag": [], "helpText": "Ensure external file sharing in Teams is enabled for only approved cloud storage services.", "addedComponent": [ { @@ -2816,13 +3280,14 @@ "label": "Define approved cloud storage services for external file sharing in Teams", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-07-28", "powershellEquivalent": "Set-CsTeamsClientConfiguration -AllowGoogleDrive $false -AllowShareFile $false -AllowBox $false -AllowDropBox $false -AllowEgnyte $false", - "recommendedBy": ["CIS 3.0"] + "recommendedBy": ["CIS"] }, { "name": "standards.TeamsEnrollUser", "cat": "Teams Standards", - "tag": ["lowimpact"], + "tag": [], "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.", "addedComponent": [ @@ -2848,13 +3313,14 @@ "label": "Default voice and face enrollment", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2024-11-12", "powershellEquivalent": "Set-CsTeamsMeetingPolicy -Identity Global -EnrollUserOverride $false", "recommendedBy": [] }, { "name": "standards.TeamsExternalAccessPolicy", "cat": "Teams Standards", - "tag": ["mediumimpact"], + "tag": [], "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.", "addedComponent": [ @@ -2877,13 +3343,14 @@ "label": "External Access Settings for Microsoft Teams", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2024-07-30", "powershellEquivalent": "Set-CsExternalAccessPolicy", "recommendedBy": [] }, { "name": "standards.TeamsFederationConfiguration", "cat": "Teams Standards", - "tag": ["mediumimpact"], + "tag": [], "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.", "addedComponent": [ @@ -2933,13 +3400,14 @@ "label": "Federation Configuration for Microsoft Teams", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2024-07-31", "powershellEquivalent": "Set-CsTenantFederationConfiguration", "recommendedBy": [] }, { "name": "standards.TeamsMessagingPolicy", "cat": "Teams Standards", - "tag": ["mediumimpact"], + "tag": [], "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.", "addedComponent": [ @@ -2947,25 +3415,25 @@ "type": "switch", "name": "standards.TeamsMessagingPolicy.AllowOwnerDeleteMessage", "label": "Allow Owner to Delete Messages", - "default": false + "defaultValue": false }, { "type": "switch", "name": "standards.TeamsMessagingPolicy.AllowUserDeleteMessage", "label": "Allow User to Delete Messages", - "default": true + "defaultValue": true }, { "type": "switch", "name": "standards.TeamsMessagingPolicy.AllowUserEditMessage", "label": "Allow User to Edit Messages", - "default": true + "defaultValue": true }, { "type": "switch", "name": "standards.TeamsMessagingPolicy.AllowUserDeleteChat", "label": "Allow User to Delete Chats", - "default": true + "defaultValue": true }, { "type": "autoComplete", @@ -2993,37 +3461,38 @@ "type": "switch", "name": "standards.TeamsMessagingPolicy.CreateCustomEmojis", "label": "Allow Creating Custom Emojis", - "default": true + "defaultValue": true }, { "type": "switch", "name": "standards.TeamsMessagingPolicy.DeleteCustomEmojis", "label": "Allow Deleting Custom Emojis", - "default": false + "defaultValue": false }, { "type": "switch", "name": "standards.TeamsMessagingPolicy.AllowSecurityEndUserReporting", "label": "Allow reporting message as security concern", - "default": true + "defaultValue": true }, { "type": "switch", "name": "standards.TeamsMessagingPolicy.AllowCommunicationComplianceEndUserReporting", "label": "Allow reporting message as inappropriate content", - "default": true + "defaultValue": true } ], "label": "Global Messaging Policy for Microsoft Teams", "impact": "Medium Impact", "impactColour": "warning", + "addedDate": "2025-01-10", "powershellEquivalent": "Set-CsTeamsMessagingPolicy", "recommendedBy": [] }, { "name": "standards.AutopilotStatusPage", "cat": "Device Management Standards", - "tag": ["lowimpact"], + "tag": [], "disabledFeatures": { "report": true, "warn": true, @@ -3036,65 +3505,67 @@ "type": "number", "name": "standards.AutopilotStatusPage.TimeOutInMinutes", "label": "Timeout in minutes", - "default": 60 + "defaultValue": 60 }, { "type": "textField", "name": "standards.AutopilotStatusPage.ErrorMessage", - "label": "Custom Error Message" + "label": "Custom Error Message", + "required": false }, { "type": "switch", "name": "standards.AutopilotStatusPage.ShowProgress", "label": "Show progress to users", - "default": true + "defaultValue": true }, { "type": "switch", "name": "standards.AutopilotStatusPage.EnableLog", "label": "Turn on log collection", - "default": true + "defaultValue": true }, { "type": "switch", "name": "standards.AutopilotStatusPage.OBEEOnly", "label": "Show status page only with OOBE setup", - "default": true + "defaultValue": true }, { "type": "switch", "name": "standards.AutopilotStatusPage.BlockDevice", "label": "Block device usage during setup", - "default": true + "defaultValue": true }, { "type": "switch", "name": "standards.AutopilotStatusPage.AllowRetry", "label": "Allow retry", - "default": true + "defaultValue": true }, { "type": "switch", "name": "standards.AutopilotStatusPage.AllowReset", "label": "Allow reset", - "default": true + "defaultValue": true }, { "type": "switch", "name": "standards.AutopilotStatusPage.AllowFail", "label": "Allow users to use device if setup fails", - "default": true + "defaultValue": true } ], "label": "Enable Autopilot Status Page", "impact": "Low Impact", + "addedDate": "2023-12-30", "impactColour": "info", "recommendedBy": [] }, { "name": "standards.AutopilotProfile", "cat": "Device Management Standards", - "tag": ["lowimpact"], + "tag": [], "disabledFeatures": { "report": true, "warn": true, @@ -3134,60 +3605,61 @@ "type": "switch", "name": "standards.AutopilotProfile.CollectHash", "label": "Convert all targeted devices to Autopilot", - "default": true + "defaultValue": true }, { "type": "switch", "name": "standards.AutopilotProfile.AssignToAllDevices", "label": "Assign to all devices", - "default": true + "defaultValue": true }, { "type": "switch", "name": "standards.AutopilotProfile.SelfDeployingMode", "label": "Enable Self-deploying Mode", - "default": true + "defaultValue": true }, { "type": "switch", "name": "standards.AutopilotProfile.HideTerms", "label": "Hide Terms and Conditions", - "default": true + "defaultValue": true }, { "type": "switch", "name": "standards.AutopilotProfile.HidePrivacy", "label": "Hide Privacy Settings", - "default": true + "defaultValue": true }, { "type": "switch", "name": "standards.AutopilotProfile.HideChangeAccount", "label": "Hide Change Account Options", - "default": true + "defaultValue": true }, { "type": "switch", "name": "standards.AutopilotProfile.NotLocalAdmin", "label": "Setup user as a standard user (not local admin)", - "default": true + "defaultValue": true }, { "type": "switch", "name": "standards.AutopilotProfile.AllowWhiteGlove", "label": "Allow White Glove OOBE", - "default": true + "defaultValue": true }, { "type": "switch", "name": "standards.AutopilotProfile.AutoKeyboard", "label": "Automatically configure keyboard", - "default": true + "defaultValue": true } ], "label": "Enable Autopilot Profile", "impact": "Low Impact", "impactColour": "info", + "addedDate": "2023-12-30", "recommendedBy": [] }, { @@ -3196,11 +3668,12 @@ "label": "Intune Template", "multiple": true, "disabledFeatures": { - "report": true, - "warn": true, + "report": false, + "warn": false, "remediate": false }, - "impact": "High", + "impact": "High Impact", + "addedDate": "2023-12-30", "helpText": "Deploy and manage Intune templates across devices.", "addedComponent": [ { @@ -3224,10 +3697,7 @@ { "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 all users and devices", "value": "AllDevicesAndUsers" }, { "label": "Assign to Custom Group", "value": "customGroup" } ] }, @@ -3236,6 +3706,13 @@ "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." } ] }, @@ -3248,7 +3725,8 @@ "warn": true, "remediate": false }, - "impact": "Medium", + "impact": "Medium Impact", + "addedDate": "2023-12-30", "helpText": "Deploy transport rules to manage email flow.", "addedComponent": [ { @@ -3274,7 +3752,8 @@ "warn": true, "remediate": false }, - "impact": "High", + "impact": "High Impact", + "addedDate": "2023-12-30", "helpText": "Manage conditional access policies for better security.", "addedComponent": [ { @@ -3297,10 +3776,7 @@ { "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" - } + { "value": "enabledForReportingButNotEnforced", "label": "Set to report only" } ] } ] @@ -3313,7 +3789,8 @@ "warn": true, "remediate": false }, - "impact": "Medium", + "impact": "Medium Impact", + "addedDate": "2023-12-30", "helpText": "Deploy and manage Exchange connectors.", "addedComponent": [ { @@ -3339,7 +3816,8 @@ "warn": true, "remediate": false }, - "impact": "Medium", + "impact": "Medium Impact", + "addedDate": "2023-12-30", "helpText": "Deploy and manage group templates.", "addedComponent": [ { diff --git a/Modules/CIPPCore/Public/Add-CIPPApplicationPermission.ps1 b/Modules/CIPPCore/Public/Add-CIPPApplicationPermission.ps1 index b4b6c7d177ca..8841b33e8abc 100644 --- a/Modules/CIPPCore/Public/Add-CIPPApplicationPermission.ps1 +++ b/Modules/CIPPCore/Public/Add-CIPPApplicationPermission.ps1 @@ -5,7 +5,7 @@ function Add-CIPPApplicationPermission { $ApplicationId, $Tenantfilter ) - if ($ApplicationId -eq $ENV:ApplicationID -and $Tenantfilter -eq $env:TenantID) { + if ($ApplicationId -eq $env:ApplicationID -and $Tenantfilter -eq $env:TenantID) { #return @('Cannot modify application permissions for CIPP-SAM on partner tenant') $RequiredResourceAccess = 'CIPPDefaults' } diff --git a/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1 b/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1 index f7692236596d..a67ab955d4bb 100644 --- a/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1 +++ b/Modules/CIPPCore/Public/Add-CIPPAzDataTableEntity.ps1 @@ -23,31 +23,32 @@ function Add-CIPPAzDataTableEntity { $Parameters.OperationType = $OperationType } - $MaxRowSize = 500000 - 100 # Maximum size of an entity - $MaxSize = 30kb # Maximum size of a property value + $MaxRowSize = 500000 - 100 + $MaxSize = 30kb foreach ($SingleEnt in @($Entity)) { try { if ($null -eq $SingleEnt.PartitionKey -or $null -eq $SingleEnt.RowKey) { throw 'PartitionKey or RowKey is null' } + Add-AzDataTableEntity @Parameters -Entity $SingleEnt -ErrorAction Stop + } catch [System.Exception] { - if ($_.Exception.ErrorCode -eq 'PropertyValueTooLarge' -or $_.Exception.ErrorCode -eq 'EntityTooLarge' -or $_.Exception.ErrorCode -eq 'RequestBodyTooLarge') { + if ($_.Exception.ErrorCode -in @('PropertyValueTooLarge', 'EntityTooLarge', 'RequestBodyTooLarge')) { try { Write-Host 'Entity is too large. Splitting entity into multiple parts.' - #Write-Information ($SingleEnt | ConvertTo-Json) + $largePropertyNames = [System.Collections.Generic.List[string]]::new() $entitySize = 0 - # Convert $SingleEnt to hashtable if it is a PSObject if ($SingleEnt -is [System.Management.Automation.PSCustomObject]) { $SingleEnt = $SingleEnt | ConvertTo-Json -Depth 100 -Compress | ConvertFrom-Json -AsHashtable } foreach ($key in $SingleEnt.Keys) { $propertySize = [System.Text.Encoding]::UTF8.GetByteCount($SingleEnt[$key].ToString()) - $entitySize = $entitySize + $propertySize + $entitySize += $propertySize if ($propertySize -gt $MaxSize) { $largePropertyNames.Add($key) } @@ -63,7 +64,7 @@ function Add-CIPPAzDataTableEntity { $start = $i * $MaxSize $splitData.Add($dataString.Substring($start, [Math]::Min($MaxSize, $dataString.Length - $start))) > $null } - $splitDataCount = ($splitData | Measure-Object).Count + $splitDataCount = $splitData.Count $splitPropertyNames = [System.Collections.Generic.List[object]]::new() for ($i = 0; $i -lt $splitDataCount; $i++) { $splitPropertyNames.Add("${largePropertyName}_Part$i") @@ -80,11 +81,9 @@ function Add-CIPPAzDataTableEntity { $SingleEnt[$splitPropertyNames[$i]] = $splitData[$i] } } - $SingleEnt['SplitOverProps'] = ($splitInfoList | ConvertTo-Json -Compress).ToString() } - # Check if the entity is still too large $entitySize = [System.Text.Encoding]::UTF8.GetByteCount($($SingleEnt | ConvertTo-Json -Compress)) if ($entitySize -gt $MaxRowSize) { $rows = [System.Collections.Generic.List[object]]::new() @@ -96,11 +95,7 @@ function Add-CIPPAzDataTableEntity { Write-Information "Entity size is $entitySize. Splitting entity into multiple parts." $newEntity = @{} $newEntity['PartitionKey'] = $originalPartitionKey - if ($entityIndex -eq 0) { - $newEntity['RowKey'] = $originalRowKey - } else { - $newEntity['RowKey'] = "$($originalRowKey)-part$entityIndex" - } + $newEntity['RowKey'] = if ($entityIndex -eq 0) { $originalRowKey } else { "$($originalRowKey)-part$entityIndex" } $newEntity['OriginalEntityId'] = $originalRowKey $newEntity['PartIndex'] = $entityIndex $entityIndex++ @@ -142,12 +137,11 @@ function Add-CIPPAzDataTableEntity { $entitySize = [System.Text.Encoding]::UTF8.GetByteCount($($SingleEnt | ConvertTo-Json -Compress)) } - if (($SingleEnt | Measure-Object).Count -gt 0) { + if ($SingleEnt.Count -gt 0) { $SingleEnt['RowKey'] = "$($originalRowKey)-part$entityIndex" $SingleEnt['OriginalEntityId'] = $originalRowKey $SingleEnt['PartIndex'] = $entityIndex $SingleEnt['PartitionKey'] = $originalPartitionKey - $rows.Add($SingleEnt) } @@ -156,14 +150,28 @@ function Add-CIPPAzDataTableEntity { $NewRow = ([PSCustomObject]$row) | Select-Object * -ExcludeProperty Timestamp Add-AzDataTableEntity @Parameters -Entity $NewRow } + } else { $NewEnt = ([PSCustomObject]$SingleEnt) | Select-Object * -ExcludeProperty Timestamp Add-AzDataTableEntity @Parameters -Entity $NewEnt + if ($NewEnt.PSObject.Properties['OriginalEntityId'] -eq $null -and $NewEnt.PSObject.Properties['PartIndex'] -eq $null) { + $partIndex = 1 + while ($true) { + $partRowKey = "$($NewEnt.RowKey)-part$partIndex" + try { + Remove-AzDataTableEntity -Context $Context -PartitionKey $NewEnt.PartitionKey -RowKey $partRowKey -ErrorAction Stop + Write-Information "Deleted obsolete part: $partRowKey" + $partIndex++ + } catch { + break + } + } + } } } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-Warning ('AzBobbyTables Error') + Write-Warning 'AzBobbyTables Error' Write-Information ($SingleEnt | ConvertTo-Json) throw "Error processing entity: $ErrorMessage Linenumber: $($_.InvocationInfo.ScriptLineNumber)" } diff --git a/Modules/CIPPCore/Public/Add-CIPPDelegatedPermission.ps1 b/Modules/CIPPCore/Public/Add-CIPPDelegatedPermission.ps1 index 5b811bbd405e..8b1b50702035 100644 --- a/Modules/CIPPCore/Public/Add-CIPPDelegatedPermission.ps1 +++ b/Modules/CIPPCore/Public/Add-CIPPDelegatedPermission.ps1 @@ -9,7 +9,7 @@ function Add-CIPPDelegatedPermission { Write-Host 'Adding Delegated Permissions' Set-Location (Get-Item $PSScriptRoot).FullName - if ($ApplicationId -eq $ENV:ApplicationID -and $Tenantfilter -eq $env:TenantID) { + if ($ApplicationId -eq $env:ApplicationID -and $Tenantfilter -eq $env:TenantID) { #return @('Cannot modify delgated permissions for CIPP-SAM on partner tenant') $RequiredResourceAccess = 'CIPPDefaults' } diff --git a/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 b/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 index 70388e578446..4a8548e0a741 100644 --- a/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 +++ b/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 @@ -1,96 +1,129 @@ function Add-CIPPScheduledTask { - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'Default')] param( + [Parameter(Mandatory = $true, ParameterSetName = 'Default')] [pscustomobject]$Task, + + [Parameter(Mandatory = $false, ParameterSetName = 'Default')] [bool]$Hidden, + + [Parameter(Mandatory = $false, ParameterSetName = 'Default')] $DisallowDuplicateName = $false, + + [Parameter(Mandatory = $false, ParameterSetName = 'Default')] [string]$SyncType = $null, + + [Parameter(Mandatory = $false, ParameterSetName = 'RunNow')] + [switch]$RunNow, + + [Parameter(Mandatory = $true, ParameterSetName = 'RunNow')] + [string]$RowKey, + + [Parameter(Mandatory = $false, ParameterSetName = 'Default')] + [Parameter(Mandatory = $false, ParameterSetName = 'RunNow')] $Headers ) $Table = Get-CIPPTable -TableName 'ScheduledTasks' - if ($DisallowDuplicateName) { - $Filter = "PartitionKey eq 'ScheduledTask' and Name eq '$($Task.Name)'" - $ExistingTask = (Get-CIPPAzDataTableEntity @Table -Filter $Filter) - if ($ExistingTask) { - return "Task with name $($Task.Name) already exists" + + if ($RunNow.IsPresent -and $RowKey) { + try { + $Filter = "PartitionKey eq 'ScheduledTask' and RowKey eq '$($RowKey)'" + $ExistingTask = (Get-CIPPAzDataTableEntity @Table -Filter $Filter) + $ExistingTask.ScheduledTime = [int64](([datetime]::UtcNow) - (Get-Date '1/1/1970')).TotalSeconds + $ExistingTask.TaskState = 'Planned' + Add-CIPPAzDataTableEntity @Table -Entity $ExistingTask -Force + Write-LogMessage -headers $Headers -API 'RunNow' -message "Task $($ExistingTask.Name) scheduled to run now" -Sev 'Info' -Tenant $ExistingTask.Tenant + return "Task $($ExistingTask.Name) scheduled to run now" + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -headers $Headers -API 'RunNow' -message "Could not run task: $ErrorMessage" -Sev 'Error' + return "Could not run task: $ErrorMessage" + } + } else { + if ($DisallowDuplicateName) { + $Filter = "PartitionKey eq 'ScheduledTask' and Name eq '$($Task.Name)'" + $ExistingTask = (Get-CIPPAzDataTableEntity @Table -Filter $Filter) + if ($ExistingTask) { + return "Task with name $($Task.Name) already exists" + } } - } - $propertiesToCheck = @('Webhook', 'Email', 'PSA') - $PostExecutionObject = ($propertiesToCheck | Where-Object { $task.PostExecution.$_ -eq $true }) - $PostExecution = $PostExecutionObject ? ($PostExecutionObject -join ',') : ($Task.PostExecution.value -join ',') - $Parameters = [System.Collections.Hashtable]@{} - foreach ($Key in $task.Parameters.PSObject.Properties.Name) { - $Param = $task.Parameters.$Key + $propertiesToCheck = @('Webhook', 'Email', 'PSA') + $PostExecutionObject = ($propertiesToCheck | Where-Object { $task.PostExecution.$_ -eq $true }) + $PostExecution = $PostExecutionObject ? ($PostExecutionObject -join ',') : ($Task.PostExecution.value -join ',') + $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()) { - $ht[$p.Key] = $p.Value + 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()) { + $ht[$p.Key] = $p.Value + } + $Parameters[$Key] = [PSCustomObject]$ht + } else { + $Parameters[$Key] = $Param } - $Parameters[$Key] = [PSCustomObject]$ht - } else { - $Parameters[$Key] = $Param } - } - if ($Headers) { - $Parameters.Headers = $Headers | Select-Object -Property 'x-forwarded-for', 'x-ms-client-principal', 'x-ms-client-principal-idp', 'x-ms-client-principal-name' - } + if ($Headers) { + $Parameters.Headers = $Headers | Select-Object -Property 'x-forwarded-for', 'x-ms-client-principal', 'x-ms-client-principal-idp', 'x-ms-client-principal-name' + } - $Parameters = ($Parameters | ConvertTo-Json -Depth 10 -Compress) - $AdditionalProperties = [System.Collections.Hashtable]@{} - foreach ($Prop in $task.AdditionalProperties) { - $AdditionalProperties[$Prop.Key] = $Prop.Value - } - $AdditionalProperties = ([PSCustomObject]$AdditionalProperties | ConvertTo-Json -Compress) - if ($Parameters -eq 'null') { $Parameters = '' } - if (!$Task.RowKey) { - $RowKey = (New-Guid).Guid - } else { - $RowKey = $Task.RowKey - } + $Parameters = ($Parameters | ConvertTo-Json -Depth 10 -Compress) + $AdditionalProperties = [System.Collections.Hashtable]@{} + foreach ($Prop in $task.AdditionalProperties) { + $AdditionalProperties[$Prop.Key] = $Prop.Value + } + $AdditionalProperties = ([PSCustomObject]$AdditionalProperties | ConvertTo-Json -Compress) + if ($Parameters -eq 'null') { $Parameters = '' } + if (!$Task.RowKey) { + $RowKey = (New-Guid).Guid + } else { + $RowKey = $Task.RowKey + } - $Recurrence = if ([string]::IsNullOrEmpty($task.Recurrence.value)) { - $task.Recurrence - } else { - $task.Recurrence.value - } + $Recurrence = if ([string]::IsNullOrEmpty($task.Recurrence.value)) { + $task.Recurrence + } else { + $task.Recurrence.value + } - if ([int64]$task.ScheduledTime -eq 0 -or [string]::IsNullOrEmpty($task.ScheduledTime)) { - $task.ScheduledTime = [int64](([datetime]::UtcNow) - (Get-Date '1/1/1970')).TotalSeconds - } - $excludedTenants = if ($task.excludedTenants.value) { - $task.excludedTenants.value -join ',' - } - $entity = @{ - PartitionKey = [string]'ScheduledTask' - TaskState = [string]'Planned' - RowKey = [string]$RowKey - Tenant = $task.TenantFilter.value ? "$($task.TenantFilter.value)" : "$($task.TenantFilter)" - excludedTenants = [string]$excludedTenants - Name = [string]$task.Name - Command = [string]$task.Command.value - Parameters = [string]$Parameters - ScheduledTime = [string]$task.ScheduledTime - Recurrence = [string]$Recurrence - PostExecution = [string]$PostExecution - AdditionalProperties = [string]$AdditionalProperties - Hidden = [bool]$Hidden - Results = 'Planned' - } - if ($SyncType) { - $entity.SyncType = $SyncType - } - try { - Add-CIPPAzDataTableEntity @Table -Entity $entity -Force - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - return "Could not add task: $ErrorMessage" + if ([int64]$task.ScheduledTime -eq 0 -or [string]::IsNullOrEmpty($task.ScheduledTime)) { + $task.ScheduledTime = [int64](([datetime]::UtcNow) - (Get-Date '1/1/1970')).TotalSeconds + } + $excludedTenants = if ($task.excludedTenants.value) { + $task.excludedTenants.value -join ',' + } + $entity = @{ + PartitionKey = [string]'ScheduledTask' + TaskState = [string]'Planned' + RowKey = [string]$RowKey + Tenant = $task.TenantFilter.value ? "$($task.TenantFilter.value)" : "$($task.TenantFilter)" + excludedTenants = [string]$excludedTenants + Name = [string]$task.Name + Command = [string]$task.Command.value + Parameters = [string]$Parameters + ScheduledTime = [string]$task.ScheduledTime + Recurrence = [string]$Recurrence + PostExecution = [string]$PostExecution + AdditionalProperties = [string]$AdditionalProperties + Hidden = [bool]$Hidden + Results = 'Planned' + } + if ($SyncType) { + $entity.SyncType = $SyncType + } + try { + Add-CIPPAzDataTableEntity @Table -Entity $entity -Force + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + return "Could not add task: $ErrorMessage" + } + return "Successfully added task: $($entity.Name)" } - return "Successfully added task: $($entity.Name)" } diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertNewAppApproval.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertNewAppApproval.ps1 index e7e9ba47816e..69889ea73ec2 100644 --- a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertNewAppApproval.ps1 +++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertNewAppApproval.ps1 @@ -9,7 +9,8 @@ function Get-CIPPAlertNewAppApproval { [Parameter(Mandatory = $false)] [Alias('input')] $InputValue, - $TenantFilter + $TenantFilter, + $Headers ) try { $Approvals = New-GraphGetRequest -Uri "https://graph.microsoft.com/v1.0/identityGovernance/appConsent/appConsentRequests?`$filter=userConsentRequests/any (u:u/status eq 'InProgress')" -tenantid $TenantFilter diff --git a/Modules/CIPPCore/Public/Authentication/Get-CippApiAuth.ps1 b/Modules/CIPPCore/Public/Authentication/Get-CippApiAuth.ps1 index 5b8760235e64..3056fdb0c8d9 100644 --- a/Modules/CIPPCore/Public/Authentication/Get-CippApiAuth.ps1 +++ b/Modules/CIPPCore/Public/Authentication/Get-CippApiAuth.ps1 @@ -7,7 +7,8 @@ function Get-CippApiAuth { if ($env:MSI_SECRET) { Disable-AzContextAutosave -Scope Process | Out-Null $null = Connect-AzAccount -Identity - $SubscriptionId = $ENV:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 + $SubscriptionId = $env:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 + $Context = Set-AzContext -SubscriptionId $SubscriptionId } else { $Context = Get-AzContext $SubscriptionId = $Context.Subscription.Id diff --git a/Modules/CIPPCore/Public/Authentication/New-CIPPAPIConfig.ps1 b/Modules/CIPPCore/Public/Authentication/New-CIPPAPIConfig.ps1 index aa0da8936ab5..43bbee34f7a2 100644 --- a/Modules/CIPPCore/Public/Authentication/New-CIPPAPIConfig.ps1 +++ b/Modules/CIPPCore/Public/Authentication/New-CIPPAPIConfig.ps1 @@ -55,12 +55,13 @@ function New-CIPPAPIConfig { enableAccessTokenIssuance = $false enableIdTokenIssuance = $true } - redirectUris = @("https://$($ENV:Website_hostname)/.auth/login/aad/callback") + redirectUris = @("https://$($env:WEBSITE_HOSTNAME)/.auth/login/aad/callback") } } | ConvertTo-Json -Depth 10 -Compress if ($PSCmdlet.ShouldProcess($AppName, 'Create API App')) { Write-Information 'Creating app' + Write-Information $CreateBody $APIApp = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/v1.0/applications' -AsApp $true -NoAuthCheck $true -type POST -body $CreateBody Write-Information 'Creating password' $APIPassword = New-GraphPOSTRequest -uri "https://graph.microsoft.com/v1.0/applications/$($APIApp.id)/addPassword" -AsApp $true -NoAuthCheck $true -type POST -body "{`"passwordCredential`":{`"displayName`":`"Generated by API Setup`"}}" @@ -118,9 +119,6 @@ function New-CIPPAPIConfig { $ErrorMessage = Get-CippException -Exception $_ Write-Information ($ErrorMessage | ConvertTo-Json -Depth 10) Write-LogMessage -headers $Headers -API $APINAME -tenant 'None' -message "Failed to setup CIPP-API Access: $($ErrorMessage.NormalizedError) Linenumber: $($_.InvocationInfo.ScriptLineNumber)" -Sev 'Error' -LogData $ErrorMessage - return @{ - Results = "Failed to setup CIPP-API Access: $($ErrorMessage.NormalizedError)" - } - + throw "Failed to setup CIPP-API Access: $($ErrorMessage.NormalizedError)" } } diff --git a/Modules/CIPPCore/Public/Authentication/Set-CippApiAuth.ps1 b/Modules/CIPPCore/Public/Authentication/Set-CippApiAuth.ps1 index e6ebd0b46609..b6c9278c45a5 100644 --- a/Modules/CIPPCore/Public/Authentication/Set-CippApiAuth.ps1 +++ b/Modules/CIPPCore/Public/Authentication/Set-CippApiAuth.ps1 @@ -10,7 +10,7 @@ function Set-CippApiAuth { if ($env:MSI_SECRET) { Disable-AzContextAutosave -Scope Process | Out-Null $null = Connect-AzAccount -Identity - $SubscriptionId = $ENV:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 + $SubscriptionId = $env:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 $Context = Set-AzContext -SubscriptionId $SubscriptionId } else { $Context = Get-AzContext @@ -20,6 +20,8 @@ function Set-CippApiAuth { # Get auth settings $AuthSettings = Invoke-AzRestMethod -Uri "https://management.azure.com/subscriptions/$SubscriptionId/resourceGroups/$RGName/providers/Microsoft.Web/sites/$($FunctionAppName)/config/authsettingsV2/list?api-version=2020-06-01" | Select-Object -ExpandProperty Content | ConvertFrom-Json + Write-Information "AuthSettings: $($AuthSettings | ConvertTo-Json -Depth 10)" + # Set allowed audiences $AllowedAudiences = foreach ($ClientId in $ClientIds) { "api://$ClientId" diff --git a/Modules/CIPPCore/Public/Authentication/Test-CIPPAccess.ps1 b/Modules/CIPPCore/Public/Authentication/Test-CIPPAccess.ps1 index bee272fb3afc..dea7c6587adf 100644 --- a/Modules/CIPPCore/Public/Authentication/Test-CIPPAccess.ps1 +++ b/Modules/CIPPCore/Public/Authentication/Test-CIPPAccess.ps1 @@ -144,6 +144,7 @@ function Test-CIPPAccess { throw "Access to this CIPP API endpoint is not allowed, you do not have the required permission: $APIRole" } if (!$TenantAllowed -and $Help.Functionality -notmatch 'AnyTenant') { + Write-Information "Tenant not allowed: $TenantFilter" throw 'Access to this tenant is not allowed' } else { return $true diff --git a/Modules/CIPPCore/Public/CippQueue/Invoke-RemoveCippQueue.ps1 b/Modules/CIPPCore/Public/CippQueue/Invoke-RemoveCippQueue.ps1 index a9c2a9081c6a..54633f0fd9a8 100644 --- a/Modules/CIPPCore/Public/CippQueue/Invoke-RemoveCippQueue.ps1 +++ b/Modules/CIPPCore/Public/CippQueue/Invoke-RemoveCippQueue.ps1 @@ -8,7 +8,8 @@ function Invoke-RemoveCippQueue { 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' $CippQueue = Get-CippTable -TableName 'CippQueue' Clear-AzDataTable @CippQueue diff --git a/Modules/CIPPCore/Public/Clear-CippDurables.ps1 b/Modules/CIPPCore/Public/Clear-CippDurables.ps1 index 24708181fc17..44c77f74e82c 100644 --- a/Modules/CIPPCore/Public/Clear-CippDurables.ps1 +++ b/Modules/CIPPCore/Public/Clear-CippDurables.ps1 @@ -44,7 +44,7 @@ function Clear-CippDurables { } $CippQueueTasks = Get-CippTable -TableName 'CippQueueTasks' - $RunningTasks = Get-CIPPAzDataTableEntity @CippQueueTasks -Filter "Status eq 'Running'" -Property RowKey, PartitionKey, Status + $RunningTasks = Get-CIPPAzDataTableEntity @CippQueueTasks -Filter "PartitionKey eq 'Task' and Status eq 'Running'" -Property RowKey, PartitionKey, Status if (($RunningTasks | Measure-Object).Count -gt 0) { if ($PSCmdlet.ShouldProcess('Tasks', 'Mark Failed')) { $UpdatedTasks = foreach ($Task in $RunningTasks) { diff --git a/Modules/CIPPCore/Public/Compare-CIPPIntuneObject.ps1 b/Modules/CIPPCore/Public/Compare-CIPPIntuneObject.ps1 index 5b08e91ebe79..03041d90cfa7 100644 --- a/Modules/CIPPCore/Public/Compare-CIPPIntuneObject.ps1 +++ b/Modules/CIPPCore/Public/Compare-CIPPIntuneObject.ps1 @@ -69,8 +69,8 @@ function Compare-CIPPIntuneObject { [string]$PropertyName ) return ($PropertyName -like '*@OData*' -or - $PropertyName -like '#microsoft.graph*' -or - $excludeProps -contains $PropertyName) + $PropertyName -like '#microsoft.graph*' -or + $excludeProps -contains $PropertyName) } # Recursive function to compare objects deeply @@ -83,7 +83,7 @@ function Compare-CIPPIntuneObject { $Object2, [Parameter(Mandatory = $false)] - [string]$PropertyPath = "" + [string]$PropertyPath = '' ) # If both objects are null or empty, they're equal @@ -94,20 +94,20 @@ function Compare-CIPPIntuneObject { # If one object is null but the other isn't, they're different if (($null -eq $Object1 -or $Object1 -eq '') -xor ($null -eq $Object2 -or $Object2 -eq '')) { $result.Add([PSCustomObject]@{ - Property = $PropertyPath - ExpectedValue = if ($null -eq $Object1) { '' } else { $Object1 } - ReceivedValue = if ($null -eq $Object2) { '' } else { $Object2 } - }) + Property = $PropertyPath + ExpectedValue = if ($null -eq $Object1) { '' } else { $Object1 } + ReceivedValue = if ($null -eq $Object2) { '' } else { $Object2 } + }) return } # If objects are of different types, they're different if ($Object1.GetType() -ne $Object2.GetType()) { $result.Add([PSCustomObject]@{ - Property = $PropertyPath - ExpectedValue = $Object1 - ReceivedValue = $Object2 - }) + Property = $PropertyPath + ExpectedValue = $Object1 + ReceivedValue = $Object2 + }) return } @@ -122,25 +122,25 @@ function Compare-CIPPIntuneObject { $newPath = if ($PropertyPath) { "$PropertyPath.$key" } else { $key } if ($Object1.ContainsKey($key) -and $Object2.ContainsKey($key)) { - Compare-ObjectsRecursively -Object1 $Object1[$key] -Object2 $Object2[$key] -PropertyPath $newPath - } - elseif ($Object1.ContainsKey($key)) { + #only run if both props are not null + if ($Object1[$key] -and $Object2[$key]) { + Compare-ObjectsRecursively -Object1 $Object1[$key] -Object2 $Object2[$key] -PropertyPath $newPath + } + } elseif ($Object1.ContainsKey($key)) { $result.Add([PSCustomObject]@{ - Property = $newPath - ExpectedValue = $Object1[$key] - ReceivedValue = '' - }) - } - else { + Property = $newPath + ExpectedValue = $Object1[$key] + ReceivedValue = '' + }) + } else { $result.Add([PSCustomObject]@{ - Property = $newPath - ExpectedValue = '' - ReceivedValue = $Object2[$key] - }) + Property = $newPath + ExpectedValue = '' + ReceivedValue = $Object2[$key] + }) } } - } - elseif ($Object1 -is [Array] -or $Object1 -is [System.Collections.IList]) { + } elseif ($Object1 -is [Array] -or $Object1 -is [System.Collections.IList]) { # Compare arrays $maxLength = [Math]::Max($Object1.Count, $Object2.Count) @@ -149,24 +149,21 @@ function Compare-CIPPIntuneObject { if ($i -lt $Object1.Count -and $i -lt $Object2.Count) { Compare-ObjectsRecursively -Object1 $Object1[$i] -Object2 $Object2[$i] -PropertyPath $newPath - } - elseif ($i -lt $Object1.Count) { + } elseif ($i -lt $Object1.Count) { $result.Add([PSCustomObject]@{ - Property = $newPath - ExpectedValue = $Object1[$i] - ReceivedValue = '' - }) - } - else { + Property = $newPath + ExpectedValue = $Object1[$i] + ReceivedValue = '' + }) + } else { $result.Add([PSCustomObject]@{ - Property = $newPath - ExpectedValue = '' - ReceivedValue = $Object2[$i] - }) + Property = $newPath + ExpectedValue = '' + ReceivedValue = $Object2[$i] + }) } } - } - elseif ($Object1 -is [PSCustomObject] -or $Object1.PSObject.Properties.Count -gt 0) { + } elseif ($Object1 -is [PSCustomObject] -or $Object1.PSObject.Properties.Count -gt 0) { # Compare PSCustomObjects or objects with properties $allPropertyNames = @( $Object1.PSObject.Properties | Select-Object -ExpandProperty Name @@ -181,35 +178,35 @@ function Compare-CIPPIntuneObject { $prop2Exists = $Object2.PSObject.Properties.Name -contains $propName if ($prop1Exists -and $prop2Exists) { - Compare-ObjectsRecursively -Object1 $Object1.$propName -Object2 $Object2.$propName -PropertyPath $newPath - } - elseif ($prop1Exists) { + #only run if both props are not null + if ($Object1.$propName -and $Object2.$propName) { + Compare-ObjectsRecursively -Object1 $Object1.$propName -Object2 $Object2.$propName -PropertyPath $newPath + } + } elseif ($prop1Exists) { $result.Add([PSCustomObject]@{ - Property = $newPath - ExpectedValue = $Object1.$propName - ReceivedValue = '' - }) - } - else { + Property = $newPath + ExpectedValue = $Object1.$propName + ReceivedValue = '' + }) + } else { $result.Add([PSCustomObject]@{ - Property = $newPath - ExpectedValue = '' - ReceivedValue = $Object2.$propName - }) + Property = $newPath + ExpectedValue = '' + ReceivedValue = $Object2.$propName + }) } } - } - else { + } else { # Compare primitive values $val1 = $Object1.ToString() $val2 = $Object2.ToString() if ($val1 -ne $val2) { $result.Add([PSCustomObject]@{ - Property = $PropertyPath - ExpectedValue = $val1 - ReceivedValue = $val2 - }) + Property = $PropertyPath + ExpectedValue = $val1 + ReceivedValue = $val2 + }) } } } @@ -228,7 +225,10 @@ function Compare-CIPPIntuneObject { } # Start the recursive comparison - Compare-ObjectsRecursively -Object1 $obj1 -Object2 $obj2 + #only do the compare if the objects are not null + if ($obj1 -and $obj2) { + Compare-ObjectsRecursively -Object1 $obj1 -Object2 $obj2 + } # If no differences found, return null if ($result.Count -eq 0) { diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/BEC/Push-BECRun.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/BEC/Push-BECRun.ps1 index bcfd1dd7262b..b23079f413bb 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/BEC/Push-BECRun.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/BEC/Push-BECRun.ps1 @@ -96,7 +96,8 @@ function Push-BECRun { Write-Information 'Getting rules' try { - $RulesLog = New-ExoRequest -cmdlet 'Get-InboxRule' -tenantid $TenantFilter -cmdParams @{ Mailbox = $Username; IncludeHidden = $true } -Anchor $Username + $RulesLog = New-ExoRequest -cmdlet 'Get-InboxRule' -tenantid $TenantFilter -cmdParams @{ Mailbox = $Username; IncludeHidden = $true } -Anchor $Username | + Where-Object { $_.Name -ne 'Junk E-Mail Rule' -and $_.Name -notlike 'Microsoft.Exchange.OOF.*' } } catch { Write-Host 'Failed to get rules: ' + $_.Exception.Message $RulesLog = @() 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 6249f4cde350..dc7c33e94bd5 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 @@ -40,12 +40,16 @@ function Push-ListGraphRequestQueue { $RawGraphRequest = try { $Results = Get-GraphRequestList @GraphRequestParams - $Results | Select-Object -First ($Results.Count - 1) + if ($Results[-1].PSObject.Properties.Name -contains 'nextLink') { + $Results | Select-Object -First ($Results.Count - 1) + } else { + $Results + } } catch { $CippException = Get-CippException -Exception $_.Exception [PSCustomObject]@{ - Tenant = $Item.TenantFilter - CippStatus = "Could not connect to tenant. $($CippException.NormalizedMessage)" + Tenant = $Item.TenantFilter + CippStatus = "Could not connect to tenant. $($CippException.NormalizedMessage)" CippException = [string]($CippException | ConvertTo-Json -Depth 10 -Compress) } } diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecOnboardTenantQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecOnboardTenantQueue.ps1 index 172e152c38e6..f86338644252 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecOnboardTenantQueue.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecOnboardTenantQueue.ps1 @@ -233,7 +233,8 @@ Function Push-ExecOnboardTenantQueue { $Logs.Add([PSCustomObject]@{ Date = (Get-Date).ToUniversalTime(); Log = 'Checking for missing groups for SAM user' }) $SamUserId = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/me?`$select=id" -NoAuthCheck $true).id $CurrentMemberships = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/me/transitiveMemberOf?`$select=id,displayName" -NoAuthCheck $true - foreach ($Role in $Item.Roles) { + $ExpectedCippRoles = $Item.Roles | Where-Object { $_.roleDefinitionId -in $ExpectedRoles.roleDefinitionId } + foreach ($Role in $ExpectedCippRoles) { if ($CurrentMemberships.id -notcontains $Role.GroupId) { $PostBody = @{ '@odata.id' = 'https://graph.microsoft.com/v1.0/directoryObjects/{0}' -f $SamUserId @@ -315,8 +316,8 @@ Function Push-ExecOnboardTenantQueue { $LastCPVError = '' do { try { - Add-CIPPApplicationPermission -RequiredResourceAccess 'CIPPDefaults' -ApplicationId $ENV:ApplicationID -tenantfilter $Relationship.customer.tenantId - Add-CIPPDelegatedPermission -RequiredResourceAccess 'CIPPDefaults' -ApplicationId $ENV:ApplicationID -tenantfilter $Relationship.customer.tenantId + Add-CIPPApplicationPermission -RequiredResourceAccess 'CIPPDefaults' -ApplicationId $env:ApplicationID -tenantfilter $Relationship.customer.tenantId + Add-CIPPDelegatedPermission -RequiredResourceAccess 'CIPPDefaults' -ApplicationId $env:ApplicationID -tenantfilter $Relationship.customer.tenantId $CPVSuccess = $true $Refreshing = $false } catch { diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 index 460ea3456778..bf47a28af856 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 @@ -13,6 +13,12 @@ function Push-ExecScheduledCommand { $Tenant = $Item.Parameters.TenantFilter ?? $Item.TaskInfo.Tenant $TenantInfo = Get-Tenants -TenantFilter $Tenant + $null = Update-AzDataTableEntity -Force @Table -Entity @{ + PartitionKey = $task.PartitionKey + RowKey = $task.RowKey + TaskState = 'Running' + } + $Function = Get-Command -Name $Item.Command if ($null -eq $Function) { $Results = "Task Failed: The command $($Item.Command) does not exist." @@ -23,6 +29,7 @@ function Push-ExecScheduledCommand { Results = "$Results" TaskState = $State } + 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 } @@ -75,7 +82,14 @@ function Push-ExecScheduledCommand { } if ($StoredResults.Length -gt 64000 -or $task.Tenant -eq 'AllTenants') { - $StoredResults = @{ Results = 'The results for this query are too long to store in this table, or the query was meant for All Tenants. Please use the options to send the results to another target to be able to view the results. ' } | ConvertTo-Json -Compress + $TaskResultsTable = Get-CippTable -tablename 'ScheduledTaskResults' + $TaskResults = @{ + PartitionKey = $task.RowKey + RowKey = $Tenant + Results = [string](ConvertTo-Json -Compress -Depth 20 $results) + } + $null = Add-AzDataTableEntity @TaskResultsTable -Entity $TaskResults -Force + $StoredResults = @{ Results = 'Completed, details are available in the More Info pane' } | ConvertTo-Json -Compress } } catch { $errorMessage = $_.Exception.Message @@ -112,42 +126,47 @@ function Push-ExecScheduledCommand { } Write-Host 'Sent the results to the target. Updating the task state.' - if ($task.Recurrence -eq '0' -or [string]::IsNullOrEmpty($task.Recurrence)) { - Write-Host 'Recurrence empty or 0. Task is not recurring. Setting task state to completed.' - Update-AzDataTableEntity -Force @Table -Entity @{ - PartitionKey = $task.PartitionKey - RowKey = $task.RowKey - Results = "$StoredResults" - TaskState = 'Completed' - } - } else { - #if recurrence is just a number, add it in days. - if ($task.Recurrence -match '^\d+$') { - $task.Recurrence = $task.Recurrence + 'd' - } - $secondsToAdd = switch -Regex ($task.Recurrence) { - '(\d+)m$' { [int64]$matches[1] * 60 } - '(\d+)h$' { [int64]$matches[1] * 3600 } - '(\d+)d$' { [int64]$matches[1] * 86400 } - default { throw "Unsupported recurrence format: $($task.Recurrence)" } - } + try { + if ($task.Recurrence -eq '0' -or [string]::IsNullOrEmpty($task.Recurrence)) { + Write-Host 'Recurrence empty or 0. Task is not recurring. Setting task state to completed.' + Update-AzDataTableEntity -Force @Table -Entity @{ + PartitionKey = $task.PartitionKey + RowKey = $task.RowKey + Results = "$StoredResults" + TaskState = 'Completed' + } + } else { + #if recurrence is just a number, add it in days. + if ($task.Recurrence -match '^\d+$') { + $task.Recurrence = $task.Recurrence + 'd' + } + $secondsToAdd = switch -Regex ($task.Recurrence) { + '(\d+)m$' { [int64]$matches[1] * 60 } + '(\d+)h$' { [int64]$matches[1] * 3600 } + '(\d+)d$' { [int64]$matches[1] * 86400 } + default { 0 } + } - if ($secondsToAdd -gt 0) { - $unixtimeNow = [int64](([datetime]::UtcNow) - (Get-Date '1/1/1970')).TotalSeconds - if ([int64]$task.ScheduledTime -lt ($unixtimeNow - $secondsToAdd)) { - $task.ScheduledTime = $unixtimeNow + if ($secondsToAdd -gt 0) { + $unixtimeNow = [int64](([datetime]::UtcNow) - (Get-Date '1/1/1970')).TotalSeconds + if ([int64]$task.ScheduledTime -lt ($unixtimeNow - $secondsToAdd)) { + $task.ScheduledTime = $unixtimeNow + } } - } - $nextRunUnixTime = [int64]$task.ScheduledTime + [int64]$secondsToAdd - Write-Host "The job is recurring. It was scheduled for $($task.ScheduledTime). The next runtime should be $nextRunUnixTime" - Update-AzDataTableEntity -Force @Table -Entity @{ - PartitionKey = $task.PartitionKey - RowKey = $task.RowKey - Results = "$StoredResults" - TaskState = 'Planned' - ScheduledTime = "$nextRunUnixTime" + $nextRunUnixTime = [int64]$task.ScheduledTime + [int64]$secondsToAdd + Write-Host "The job is recurring. It was scheduled for $($task.ScheduledTime). The next runtime should be $nextRunUnixTime" + Update-AzDataTableEntity -Force @Table -Entity @{ + PartitionKey = $task.PartitionKey + RowKey = $task.RowKey + Results = "$StoredResults" + TaskState = 'Planned' + ScheduledTime = "$nextRunUnixTime" + } } + } catch { + Write-Warning "Failed to update task state: $($_.Exception.Message)" + Write-Information $_.InvocationInfo.PositionMessage } if ($TaskType -ne 'Alert') { Write-LogMessage -API 'Scheduler_UserTasks' -tenant $Tenant -tenantid $TenantInfo.customerId -message "Successfully executed task: $($task.Name)" -sev Info diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-SchedulerCIPPNotifications.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-SchedulerCIPPNotifications.ps1 index bf975e34fb03..e684cc202f73 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-SchedulerCIPPNotifications.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-SchedulerCIPPNotifications.ps1 @@ -46,7 +46,7 @@ function Push-SchedulerCIPPNotifications { Send-CIPPAlert -Type 'email' -Title $Subject -HTMLContent $HTMLContent.htmlcontent -TenantFilter $tenant -APIName 'Alerts' } } else { - $Data = ($CurrentLog | Select-Object Message, API, Tenant, Username, Severity | ConvertTo-Html -frag) + $Data = ($CurrentLog | Select-Object Message, API, Tenant, Username, Severity) $Subject = "CIPP Alert: Alerts found starting at $((Get-Date).AddMinutes(-15))" $HTMLContent = New-CIPPAlertTemplate -Data $Data -Format 'html' -InputObject 'table' Send-CIPPAlert -Type 'email' -Title $Subject -HTMLContent $HTMLContent.htmlcontent -TenantFilter $tenant -APIName 'Alerts' @@ -109,7 +109,7 @@ function Push-SchedulerCIPPNotifications { if ($config.sendtoIntegration) { try { foreach ($tenant in ($CurrentLog.Tenant | Sort-Object -Unique)) { - $Data = ($CurrentLog | Select-Object Message, API, Tenant, Username, Severity | Where-Object -Property tenant -EQ $tenant | ConvertTo-Html -frag) + $Data = ($CurrentLog | Select-Object Message, API, Tenant, Username, Severity | Where-Object -Property tenant -EQ $tenant) $HTMLContent = New-CIPPAlertTemplate -Data $Data -Format 'html' -InputObject 'table' $Title = "$tenant CIPP Alert: Alerts found starting at $((Get-Date).AddMinutes(-15))" Send-CIPPAlert -Type 'psa' -Title $Title -HTMLContent $HTMLContent.htmlcontent -TenantFilter $tenant -APIName 'Alerts' diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-UpdatePermissionsQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-UpdatePermissionsQueue.ps1 index fca8aba39668..6ab4496809db 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-UpdatePermissionsQueue.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-UpdatePermissionsQueue.ps1 @@ -16,15 +16,15 @@ function Push-UpdatePermissionsQueue { $Table = Get-CIPPTable -TableName cpvtenants $CPVRows = Get-CIPPAzDataTableEntity @Table | Where-Object -Property Tenant -EQ $Item.customerId - if (!$CPVRows -or $ENV:ApplicationID -notin $CPVRows.applicationId) { + if (!$CPVRows -or $env:ApplicationID -notin $CPVRows.applicationId) { Write-LogMessage -tenant $Item.defaultDomainName -tenantId $Item.customerId -message 'A New tenant has been added, or a new CIPP-SAM Application is in use' -Sev 'Warn' -API 'NewTenant' Write-Information 'Adding CPV permissions' Set-CIPPCPVConsent -Tenantfilter $Item.customerId $DomainRefreshRequired = $true } Write-Information 'Updating permissions' - Add-CIPPApplicationPermission -RequiredResourceAccess 'CIPPDefaults' -ApplicationId $ENV:ApplicationID -tenantfilter $Item.customerId - Add-CIPPDelegatedPermission -RequiredResourceAccess 'CIPPDefaults' -ApplicationId $ENV:ApplicationID -tenantfilter $Item.customerId + Add-CIPPApplicationPermission -RequiredResourceAccess 'CIPPDefaults' -ApplicationId $env:ApplicationID -tenantfilter $Item.customerId + Add-CIPPDelegatedPermission -RequiredResourceAccess 'CIPPDefaults' -ApplicationId $env:ApplicationID -tenantfilter $Item.customerId Write-LogMessage -tenant $Item.defaultDomainName -tenantId $Item.customerId -message "Updated permissions for $($Item.displayName)" -Sev 'Info' -API 'UpdatePermissionsQueue' if ($Item.defaultDomainName -ne 'PartnerTenant') { @@ -36,7 +36,7 @@ function Push-UpdatePermissionsQueue { $unixtime = [int64](([datetime]::UtcNow) - (Get-Date '1/1/1970')).TotalSeconds $GraphRequest = @{ LastApply = "$unixtime" - applicationId = "$($ENV:ApplicationID)" + applicationId = "$($env:ApplicationID)" Tenant = "$($Item.customerId)" PartitionKey = 'Tenant' RowKey = "$($Item.customerId)" 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 4cbfcda3b49d..2e0a928b2db2 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 @@ -116,7 +116,7 @@ function Invoke-ExecDurableFunctions { } $CippQueueTasks = Get-CippTable -TableName 'CippQueueTasks' - $RunningTasks = Get-CIPPAzDataTableEntity @CippQueueTasks -Filter "Status eq 'Running'" -Property RowKey, PartitionKey, Status + $RunningTasks = Get-CIPPAzDataTableEntity @CippQueueTasks -Filter "PartitionKey eq 'Task' and Status eq 'Running'" -Property RowKey, PartitionKey, Status if (($RunningTasks | Measure-Object).Count -gt 0) { if ($PSCmdlet.ShouldProcess('Tasks', 'Mark Failed')) { $UpdatedTasks = foreach ($Task in $RunningTasks) { 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 d200d368dfeb..c236a2bdd5ad 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 @@ -1,6 +1,6 @@ using namespace System.Net -Function Invoke-GetCippAlerts { +function Invoke-GetCippAlerts { <# .FUNCTIONALITY Entrypoint,AnyTenant @@ -19,7 +19,7 @@ Function Invoke-GetCippAlerts { $PartitionKey = Get-Date -UFormat '%Y%m%d' $Filter = "PartitionKey eq '{0}'" -f $PartitionKey $Rows = Get-CIPPAzDataTableEntity @Table -Filter $Filter | Sort-Object TableTimestamp -Descending | Select-Object -First 10 - $role = ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($request.headers.'x-ms-client-principal')) | ConvertFrom-Json).userRoles + $Role = ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Request.Headers.'x-ms-client-principal')) | ConvertFrom-Json).userRoles $CIPPVersion = $Request.Query.localversion $Version = Assert-CippVersion -CIPPVersion $CIPPVersion @@ -43,7 +43,7 @@ Function Invoke-GetCippAlerts { Write-LogMessage -message 'Your CIPP API is out of date. Please update to the latest version' -API 'Updates' -tenant 'All Tenants' -sev Alert } - if ($env:ApplicationID -eq 'LongApplicationID' -or $null -eq $ENV:ApplicationID) { + if ($env:ApplicationID -eq 'LongApplicationID' -or $null -eq $env:ApplicationID) { $Alerts.Add(@{ title = 'SAM Setup Incomplete' Alert = 'You have not yet completed your setup. Please go to the Setup Wizard in Application Settings to connect CIPP to your tenants.' @@ -60,7 +60,7 @@ Function Invoke-GetCippAlerts { type = 'error' }) } - if ($env:WEBSITE_RUN_FROM_PACKAGE -ne '1' -and $env:AzureWebJobsStorage -ne 'UseDevelopmentStorage=true') { + if ((!$env:WEBSITE_RUN_FROM_PACKAGE -or [string]::IsNullOrEmpty($env:WEBSITE_RUN_FROM_PACKAGE)) -and $env:AzureWebJobsStorage -ne 'UseDevelopmentStorage=true') { $Alerts.Add( @{ title = 'Function App in Write Mode' @@ -71,10 +71,6 @@ Function Invoke-GetCippAlerts { } if ($Rows) { $Rows | ForEach-Object { $Alerts.Add($_) } } $Alerts = @($Alerts) - $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - - # 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-PublicPing.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-PublicPing.ps1 new file mode 100644 index 000000000000..cc019f3c7714 --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-PublicPing.ps1 @@ -0,0 +1,56 @@ +function Invoke-PublicPing { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Public + #> + [CmdletBinding()] + Param( + $Request, + $TriggerMetadata + ) + + $KeepaliveTable = Get-CippTable -tablename 'CippKeepAlive' + $LastKeepalive = Get-CippAzDataTableEntity @KeepaliveTable -Filter "PartitionKey eq 'Ping' and RowKey eq 'Ping'" + + if ($LastKeepalive.Timestamp) { + $LastKeepalive = $LastKeepalive.Timestamp.DateTime.ToUniversalTime() + } else { + $LastKeepalive = (Get-Date).AddSeconds(-600).ToUniversalTime() + } + $KeepaliveInterval = -300 + $NextKeepAlive = (Get-Date).AddSeconds($KeepaliveInterval).ToUniversalTime() + + $IsColdStart = $Request.Headers.'x-ms-coldstart' -eq 1 + + if ($LastKeepalive -le $NextKeepAlive -or $IsColdStart) { + $Keepalive = @{ + PartitionKey = 'Ping' + RowKey = 'Ping' + } + Add-AzDataTableEntity @KeepaliveTable -Entity $Keepalive -Force + + if ($IsColdStart) { + $Milliseconds = 500 + } else { + $Milliseconds = 150 + } + + Start-Sleep -Milliseconds $Milliseconds + } + + $Body = @{ + Results = @{ + Message = 'Pong' + ColdStart = $IsColdStart + Timestamp = (Get-Date).ToUniversalTime() + RequestId = $TriggerMetadata.InvocationId + } + } + + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = ($Body | ConvertTo-Json -Depth 5) + }) +} 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 d6b57d97663b..b9ae61285dc4 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 @@ -38,7 +38,7 @@ Function Invoke-ExecExtensionsConfig { Write-Information 'Not sending to keyvault. Key previously set or left blank.' } else { Write-Information 'writing API Key to keyvault, and clearing.' - Write-Information "$ENV:WEBSITE_DEPLOYMENT_ID" + Write-Information "$env:WEBSITE_DEPLOYMENT_ID" if ($Body.$APIKey.APIKey) { Set-ExtensionAPIKey -Extension $APIKey -APIKey $Body.$APIKey.APIKey } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-AddScheduledItem.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-AddScheduledItem.ps1 index b013d2668806..1ec5a2d2c70d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-AddScheduledItem.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-AddScheduledItem.ps1 @@ -1,6 +1,6 @@ using namespace System.Net -Function Invoke-AddScheduledItem { +function Invoke-AddScheduledItem { <# .FUNCTIONALITY Entrypoint @@ -9,17 +9,33 @@ Function Invoke-AddScheduledItem { #> [CmdletBinding()] param($Request, $TriggerMetadata) - if ($null -eq $Request.query.hidden) { + if ($null -eq $Request.Query.hidden) { $hidden = $false } else { $hidden = $true } - $Result = Add-CIPPScheduledTask -Task $Request.body -Headers $Request.Headers -hidden $hidden -DisallowDuplicateName $Request.query.DisallowDuplicateName - Write-LogMessage -headers $Request.Headers -API $APINAME -message $Result -Sev 'Info' + if ($Request.Body.RunNow -eq $true) { + try { + $Table = Get-CIPPTable -TableName 'ScheduledTasks' + $Filter = "PartitionKey eq 'ScheduledTask' and RowKey eq '$($Request.Body.RowKey)'" + $ExistingTask = (Get-CIPPAzDataTableEntity @Table -Filter $Filter) + if ($ExistingTask) { + $Result = Add-CIPPScheduledTask -RowKey $Request.Body.RowKey -RunNow -Headers $Request.Headers + } else { + $Result = "Task with id $($Request.Body.RowKey) does not exist" + } + } catch { + Write-Warning "Error scheduling task: $($_.Exception.Message)" + Write-Information $_.InvocationInfo.PositionMessage + $Result = "Error scheduling task: $($_.Exception.Message)" + } + } else { + $Result = Add-CIPPScheduledTask -Task $Request.Body -Headers $Request.Headers -hidden $hidden -DisallowDuplicateName $Request.Query.DisallowDuplicateName + Write-LogMessage -headers $Request.Headers -API $APINAME -message $Result -Sev 'Info' + } Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK Body = @{ Results = $Result } }) - } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ListScheduledItemDetails.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ListScheduledItemDetails.ps1 new file mode 100644 index 000000000000..b9dd162b974e --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ListScheduledItemDetails.ps1 @@ -0,0 +1,171 @@ +using namespace System.Net + +function Invoke-ListScheduledItemDetails { + <# + .FUNCTIONALITY + Entrypoint,AnyTenant + .ROLE + CIPP.Scheduler.Read + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + # Get parameters from the request + $RowKey = $Request.Query.RowKey ?? $Request.Body.RowKey + + # Validate required parameters + if (-not $RowKey) { + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::BadRequest + Body = "Required parameter 'RowKey' is missing" + }) + return + } + + # Retrieve the task information + $TaskTable = Get-CIPPTable -TableName 'ScheduledTasks' + $Task = Get-CIPPAzDataTableEntity @TaskTable -Filter "RowKey eq '$RowKey' and PartitionKey eq 'ScheduledTask'" | Select-Object Name, TaskState, Command, Parameters, Recurrence, ExecutedTime, ScheduledTime, PostExecution, Tenant, Hidden, Results, Timestamp + + if (-not $Task) { + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::NotFound + Body = "Task with RowKey '$RowKey' not found" + }) + return + } + + # Process the task (similar to the way it's done in Invoke-ListScheduledItems) + if ($Task.Parameters) { + $Task.Parameters = $Task.Parameters | ConvertFrom-Json -ErrorAction SilentlyContinue + } else { + $Task | Add-Member -NotePropertyName Parameters -NotePropertyValue @{} + } + + if ($Task.Recurrence -eq 0 -or [string]::IsNullOrEmpty($Task.Recurrence)) { + $Task.Recurrence = 'Once' + } + + try { + $Task.ExecutedTime = [DateTimeOffset]::FromUnixTimeSeconds($Task.ExecutedTime).UtcDateTime + } catch {} + + try { + $Task.ScheduledTime = [DateTimeOffset]::FromUnixTimeSeconds($Task.ScheduledTime).UtcDateTime + } catch {} + + # Get the results if available + $ResultsTable = Get-CIPPTable -TableName 'ScheduledTaskResults' + $ResultsFilter = "PartitionKey eq '$RowKey'" + + $Results = Get-CIPPAzDataTableEntity @ResultsTable -Filter $ResultsFilter + + if (!$Results) { + try { + # Handle the case when we need to use Task.Results + if ($Task.Results) { + # Try to safely parse JSON or use the raw value if parsing fails + try { + if ($Task.Results -is [string]) { + $ResultString = $Task.Results.ToString().Trim() + if (($ResultString -match '^\[.*\]$') -or ($ResultString -match '^\{.*\}$')) { + $ResultData = $Task.Results | ConvertFrom-Json -ErrorAction Stop + } else { + # Not valid JSON format, use as is + $ResultData = $Task.Results + } + } else { + # Already an object, use as is + $ResultData = $Task.Results + } + } catch { + # If JSON parsing fails, use raw value + Write-LogMessage -API $APIName -message "Error parsing Task.Results as JSON: $_" -Sev 'Warning' + $ResultData = $Task.Results + } + } else { + $ResultData = $null + } + } catch { + Write-LogMessage -API $APIName -message "Error processing Task.Results: $_" -Sev 'Error' + $ResultData = $null + } + + $Results = @( + [PSCustomObject]@{ + RowKey = $Task.Tenant + Results = $ResultData + Timestamp = $Task.Timestamp + } + ) + } + + # Process the results if they exist + $ProcessedResults = [System.Collections.Generic.List[object]]::new() + foreach ($Result in $Results) { + try { + if ($null -ne $Result.Results) { + # Safe handling based on result type + if ($Result.Results -is [array] -or $Result.Results -is [System.Collections.ICollection]) { + # Already a collection, use as is + $ParsedResults = $Result.Results + } elseif ($Result.Results -is [string]) { + $ResultString = $Result.Results.ToString().Trim() + # Only try to parse as JSON if it looks like JSON + if (($ResultString -match '^\[.*\]$') -or ($ResultString -match '^\{.*\}$')) { + try { + $ParsedResults = $Result.Results | ConvertFrom-Json -ErrorAction Stop + } catch { + Write-LogMessage -API $APIName -message "Failed to parse result as JSON: $_" -Sev 'Warning' + # On failure, keep as string + $ParsedResults = $Result.Results + } + } else { + # Not valid JSON format + $ParsedResults = $Result.Results + } + } else { + # Any other object type + $ParsedResults = $Result.Results + } + + # Ensure results is always an array + if ($null -eq $ParsedResults -or 'null' -eq $ParsedResults) { + $Result.Results = @() + } else { + $Result.Results = @($ParsedResults) + } + + # Store tenant information with the result + $TenantId = $Result.RowKey + $TenantInfo = Get-Tenants -TenantFilter $TenantId -ErrorAction SilentlyContinue + if ($TenantInfo) { + $Result | Add-Member -NotePropertyName TenantName -NotePropertyValue $TenantInfo.displayName -Force + $Result | Add-Member -NotePropertyName TenantDefaultDomain -NotePropertyValue $TenantInfo.defaultDomainName -Force + $Result | Add-Member -NotePropertyName TenantId -NotePropertyValue $TenantInfo.customerId -Force + } + } + } catch { + Write-LogMessage -API $APIName -message "Error processing results for task $RowKey with tenant $($Result.RowKey): $_" -Sev 'Error' + # Set Results to an empty array to prevent further errors + $Result.Results = @() + } + $EndResult = $Result | Select-Object Timestamp, @{n = 'Tenant'; Expression = { $_.RowKey } }, Results + $ProcessedResults.Add($EndResult) + } + + # Combine task and results into one response + $Response = ConvertTo-Json -Depth 100 -InputObject @{ + Task = $Task + Details = $ProcessedResults + } + + # Return the response + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $Response + }) +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-RemoveScheduledItem.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-RemoveScheduledItem.ps1 index d6e06bfd11b4..11a0a23f8716 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-RemoveScheduledItem.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-RemoveScheduledItem.ps1 @@ -1,6 +1,6 @@ using namespace System.Net -Function Invoke-RemoveScheduledItem { +function Invoke-RemoveScheduledItem { <# .FUNCTIONALITY Entrypoint,AnyTenant @@ -13,13 +13,21 @@ Function Invoke-RemoveScheduledItem { $APIName = 'RemoveScheduledItem' $User = $Request.Headers + $RowKey = $Request.Query.id ? $Request.Query.id : $Request.Body.id $task = @{ - RowKey = $Request.Query.id ? $Request.Query.id : $Request.Body.id + RowKey = $RowKey PartitionKey = 'ScheduledTask' } $Table = Get-CIPPTable -TableName 'ScheduledTasks' Remove-AzDataTableEntity -Force @Table -Entity $task + $DetailTable = Get-CIPPTable -TableName 'ScheduledTaskDetails' + $Details = Get-CIPPAzDataTableEntity @DetailTable -Filter "PartitionKey eq '$($RowKey)'" -Property RowKey, PartitionKey, ETag + + if ($Details) { + Remove-AzDataTableEntity -Force @DetailTable -Entity $Details + } + Write-LogMessage -Headers $User -API $APINAME -message "Task removed: $($task.RowKey)" -Sev 'Info' Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ 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 5a403a6894f9..6624ed3ad3a7 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 @@ -11,7 +11,8 @@ Function Invoke-ExecAccessChecks { 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 'AccessChecks' $LastRun = (Get-Date).ToUniversalTime() @@ -29,7 +30,7 @@ Function Invoke-ExecAccessChecks { $Results = $null } if (!$Results) { - $Results = Test-CIPPAccessPermissions -tenantfilter $ENV:TenantID -APIName $APINAME -Headers $Request.Headers + $Results = Test-CIPPAccessPermissions -tenantfilter $env:TenantID -APIName $APINAME -Headers $Request.Headers } else { try { $LastRun = [DateTime]::SpecifyKind($Cache.Timestamp.DateTime, [DateTimeKind]::Utc) @@ -38,14 +39,14 @@ Function Invoke-ExecAccessChecks { } } } else { - $Results = Test-CIPPAccessPermissions -tenantfilter $ENV:TenantID -APIName $APINAME -Headers $Request.Headers + $Results = Test-CIPPAccessPermissions -tenantfilter $env:TenantID -APIName $APINAME -Headers $Request.Headers } } 'Tenants' { $AccessChecks = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq 'TenantAccessChecks'" if (!$Request.Body.TenantId) { try { - $Tenants = Get-Tenants -IncludeErrors | Where-Object { $_.customerId -ne $ENV:TenantID } + $Tenants = Get-Tenants -IncludeErrors | Where-Object { $_.customerId -ne $env:TenantID } $Results = foreach ($Tenant in $Tenants) { $TenantCheck = $AccessChecks | Where-Object -Property RowKey -EQ $Tenant.customerId | Select-Object -Property Data $TenantResult = [PSCustomObject]@{ diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecApiClient.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecApiClient.ps1 index de945a2112c9..3be1844d5811 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecApiClient.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecApiClient.ps1 @@ -50,7 +50,6 @@ function Invoke-ExecApiClient { $AddUpdateSuccess = $true } catch { $AddedText = "Could not modify App Registrations. Check the CIPP documentation for API requirements. Error: $($_.Exception.Message)" - $Body = $Body | Select-Object * -ExcludeProperty CIPPAPI } } @@ -100,14 +99,21 @@ function Invoke-ExecApiClient { } } 'GetAzureConfiguration' { - $RGName = $ENV:WEBSITE_RESOURCE_GROUP - $FunctionAppName = $ENV:WEBSITE_SITE_NAME + $Owner = $env:WEBSITE_OWNER_NAME + Write-Information "Owner: $Owner" + if ($Owner -match '^(?[^+]+)\+(?[^-]+(?:-[^-]+)*?)(?:-[^-]+webspace(?:-Linux)?)?$') { + $RGName = $Matches.RGName + } else { + $RGName = $env:WEBSITE_RESOURCE_GROUP + } + $FunctionAppName = $env:WEBSITE_SITE_NAME try { $APIClients = Get-CippApiAuth -RGName $RGName -FunctionAppName $FunctionAppName $Results = $ApiClients } catch { $Results = @{ Enabled = 'Could not get API clients, ensure you have the appropriate rights to read the Authentication settings.' + Error = (Get-CippException -Exception $_) } } $Body = @{ @@ -115,9 +121,14 @@ function Invoke-ExecApiClient { } } 'SaveToAzure' { - $TenantId = $ENV:TenantId - $RGName = $ENV:WEBSITE_RESOURCE_GROUP - $FunctionAppName = $ENV:WEBSITE_SITE_NAME + $TenantId = $env:TenantID + $Owner = $env:WEBSITE_OWNER_NAME + if ($Owner -match '^(?[^+]+)\+(?[^-]+(?:-[^-]+)*?)(?:-[^-]+webspace(?:-Linux)?)?$') { + $RGName = $Matches.RGName + } else { + $RGName = $env:WEBSITE_RESOURCE_GROUP + } + $FunctionAppName = $env:WEBSITE_SITE_NAME $AllClients = Get-CIPPAzDataTableEntity @Table -Filter 'Enabled eq true' | Where-Object { ![string]::IsNullOrEmpty($_.RowKey) } $ClientIds = $AllClients.RowKey try { @@ -125,7 +136,10 @@ function Invoke-ExecApiClient { $Body = @{ Results = 'API clients saved to Azure' } Write-LogMessage -headers $Request.Headers -API 'ExecApiClient' -message 'Saved API clients to Azure' -Sev 'Info' } catch { - $Body = @{ Results = 'Failed to save allowed API clients to Azure, ensure your function app has the appropriate rights to make changes to the Authentication settings.' } + $Body = @{ + Results = 'Failed to save allowed API clients to Azure, ensure your function app has the appropriate rights to make changes to the Authentication settings.' + Error = (Get-CippException -Exception $_) + } Write-Information (Get-CippException -Exception $_ | ConvertTo-Json) } } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecBackendURLs.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecBackendURLs.ps1 index 80c0de481eaa..011fb2739387 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecBackendURLs.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecBackendURLs.ps1 @@ -11,24 +11,33 @@ Function Invoke-ExecBackendURLs { 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' + + $Subscription = ($env:WEBSITE_OWNER_NAME).split('+') | Select-Object -First 1 + $SWAName = $env:WEBSITE_SITE_NAME -replace 'cipp', 'CIPP-SWA-' - $Subscription = ($ENV:WEBSITE_OWNER_NAME).split('+') | Select-Object -First 1 - $SWAName = $ENV:WEBSITE_SITE_NAME -replace 'cipp', 'CIPP-SWA-' # Write to the Azure Functions log stream. Write-Host 'PowerShell HTTP trigger function processed a request.' + $Owner = $env:WEBSITE_OWNER_NAME + if ($Owner -match '^(?[^+]+)\+(?[^-]+(?:-[^-]+)*?)(?:-[^-]+webspace(?:-Linux)?)?$') { + $RGName = $Matches.RGName + } else { + $RGName = $env:WEBSITE_RESOURCE_GROUP + } + $results = [PSCustomObject]@{ - ResourceGroup = "https://portal.azure.com/#@Go/resource/subscriptions/$Subscription/resourceGroups/$ENV:WEBSITE_RESOURCE_GROUP/overview" - KeyVault = "https://portal.azure.com/#@Go/resource/subscriptions/$Subscription/resourceGroups/$ENV:WEBSITE_RESOURCE_GROUP/providers/Microsoft.KeyVault/vaults/$($ENV:WEBSITE_SITE_NAME)/secrets" - FunctionApp = "https://portal.azure.com/#@Go/resource/subscriptions/$Subscription/resourceGroups/$ENV:WEBSITE_RESOURCE_GROUP/providers/Microsoft.Web/sites/$($ENV:WEBSITE_SITE_NAME)/appServices" - FunctionConfig = "https://portal.azure.com/#@Go/resource/subscriptions/$Subscription/resourceGroups/$ENV:WEBSITE_RESOURCE_GROUP/providers/Microsoft.Web/sites/$($ENV:WEBSITE_SITE_NAME)/configuration" - FunctionDeployment = "https://portal.azure.com/#@Go/resource/subscriptions/$Subscription/resourceGroups/$ENV:WEBSITE_RESOURCE_GROUP/providers/Microsoft.Web/sites/$($ENV:WEBSITE_SITE_NAME)/vstscd" - SWADomains = "https://portal.azure.com/#@Go/resource/subscriptions/$Subscription/resourceGroups/$ENV:WEBSITE_RESOURCE_GROUP/providers/Microsoft.Web/staticSites/$SWAName/customDomains" - SWARoles = "https://portal.azure.com/#@Go/resource/subscriptions/$Subscription/resourceGroups/$ENV:WEBSITE_RESOURCE_GROUP/providers/Microsoft.Web/staticSites/$SWAName/roleManagement" + ResourceGroup = "https://portal.azure.com/#@Go/resource/subscriptions/$Subscription/resourceGroups/$RGName/overview" + KeyVault = "https://portal.azure.com/#@Go/resource/subscriptions/$Subscription/resourceGroups/$RGName/providers/Microsoft.KeyVault/vaults/$($env:WEBSITE_SITE_NAME)/secrets" + FunctionApp = "https://portal.azure.com/#@Go/resource/subscriptions/$Subscription/resourceGroups/$RGName/providers/Microsoft.Web/sites/$($env:WEBSITE_SITE_NAME)/appServices" + FunctionConfig = "https://portal.azure.com/#@Go/resource/subscriptions/$Subscription/resourceGroups/$RGName/providers/Microsoft.Web/sites/$($env:WEBSITE_SITE_NAME)/configuration" + FunctionDeployment = "https://portal.azure.com/#@Go/resource/subscriptions/$Subscription/resourceGroups/$RGName/providers/Microsoft.Web/sites/$($env:WEBSITE_SITE_NAME)/vstscd" + SWADomains = "https://portal.azure.com/#@Go/resource/subscriptions/$Subscription/resourceGroups/$RGName/providers/Microsoft.Web/staticSites/$SWAName/customDomains" + SWARoles = "https://portal.azure.com/#@Go/resource/subscriptions/$Subscription/resourceGroups/$RGName/providers/Microsoft.Web/staticSites/$SWAName/roleManagement" Subscription = $Subscription - RGName = $ENV:WEBSITE_RESOURCE_GROUP - FunctionName = $ENV:WEBSITE_SITE_NAME + RGName = $RGName + FunctionName = $env:WEBSITE_SITE_NAME SWAName = $SWAName } 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 0384b3e3c350..a2e6fb31bd70 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 @@ -37,8 +37,8 @@ Function Invoke-ExecCPVPermissions { defaultDomainName = $env:TenantID } } - Add-CIPPApplicationPermission -RequiredResourceAccess 'CIPPDefaults' -ApplicationId $ENV:ApplicationID -tenantfilter $TenantFilter - Add-CIPPDelegatedPermission -RequiredResourceAccess 'CIPPDefaults' -ApplicationId $ENV:ApplicationID -tenantfilter $TenantFilter + Add-CIPPApplicationPermission -RequiredResourceAccess 'CIPPDefaults' -ApplicationId $env:ApplicationID -tenantfilter $TenantFilter + Add-CIPPDelegatedPermission -RequiredResourceAccess 'CIPPDefaults' -ApplicationId $env:ApplicationID -tenantfilter $TenantFilter if ($TenantFilter -notin @('PartnerTenant', $env:TenantID)) { Set-CIPPSAMAdminRoles -TenantFilter $TenantFilter } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCustomData.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCustomData.ps1 index 3ec3ca2f732c..739360e5f5e9 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCustomData.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecCustomData.ps1 @@ -230,7 +230,7 @@ function Invoke-ExecCustomData { } 'ListDirectoryExtensions' { try { - $Uri = "https://graph.microsoft.com/beta/applications(appId='$($env:ApplicationId)')/extensionProperties" + $Uri = "https://graph.microsoft.com/beta/applications(appId='$($env:ApplicationID)')/extensionProperties" $DirectoryExtensions = New-GraphGetRequest -uri $Uri -AsApp $true -NoAuthCheck $true -tenantid $env:TenantID $Existing = Get-CIPPAzDataTableEntity @CustomDataTable -Filter "PartitionKey eq 'DirectoryExtension'" @@ -271,7 +271,7 @@ function Invoke-ExecCustomData { throw 'Extension name, data type, and target objects are required.' } - $AppId = $env:ApplicationId # Replace with your application ID + $AppId = $env:ApplicationID # Replace with your application ID $Uri = "https://graph.microsoft.com/beta/applications(appId='$AppId')/extensionProperties" $BodyContent = @{ @@ -316,7 +316,7 @@ function Invoke-ExecCustomData { if (!$ExtensionName) { throw 'Extension name is missing in the request body.' } - $AppId = $env:ApplicationId # Replace with your application ID + $AppId = $env:ApplicationID # Replace with your application ID $Uri = "https://graph.microsoft.com/beta/applications(appId='$AppId')/extensionProperties/$ExtensionId" # Delete the directory extension from Microsoft Graph diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecDnsConfig.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecDnsConfig.ps1 index 99d071ee8035..e87e84033249 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecDnsConfig.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecDnsConfig.ps1 @@ -11,7 +11,8 @@ Function Invoke-ExecDnsConfig { 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' # List of supported resolvers $ValidResolvers = @( @@ -20,8 +21,7 @@ Function Invoke-ExecDnsConfig { 'Quad9' ) - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + $StatusCode = [HttpStatusCode]::OK try { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExcludeLicenses.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExcludeLicenses.ps1 index 1df4e0188d26..936659310732 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExcludeLicenses.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExcludeLicenses.ps1 @@ -11,11 +11,11 @@ Function Invoke-ExecExcludeLicenses { 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 ExcludedLicenses try { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExcludeTenant.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExcludeTenant.ps1 index d1beb8ca2547..03dde3c8ebcb 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExcludeTenant.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExcludeTenant.ps1 @@ -10,36 +10,40 @@ Function Invoke-ExecExcludeTenant { [CmdletBinding()] param($Request, $TriggerMetadata) - 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' - $username = $Request.Headers.'x-ms-client-principal-name' - $date = (Get-Date).tostring('yyyy-MM-dd') + # $username = $Request.Headers.'x-ms-client-principal-name' + $Username = $Headers.'x-ms-client-principal-name' ?? ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Headers.'x-ms-client-principal')) | ConvertFrom-Json).userDetails + Write-Host ($Username | ConvertTo-Json -Depth 10) + $Date = (Get-Date).ToString('yyyy-MM-dd') $TenantsTable = Get-CippTable -tablename Tenants if ($Request.Query.List) { $ExcludedFilter = "PartitionKey eq 'Tenants' and Excluded eq true" $ExcludedTenants = Get-CIPPAzDataTableEntity @TenantsTable -Filter $ExcludedFilter - Write-LogMessage -API $APINAME -headers $Request.Headers -message 'got excluded tenants list' -Sev 'Debug' + Write-LogMessage -API $APIName -headers $Headers -message 'got excluded tenants list' -Sev 'Debug' $body = @($ExcludedTenants) - } elseif ($Request.query.ListAll) { - $ExcludedTenants = Get-CIPPAzDataTableEntity @TenantsTable -filter "PartitionKey eq 'Tenants'" | Sort-Object -Property displayName - Write-LogMessage -API $APINAME -headers $Request.Headers -message 'got excluded tenants list' -Sev 'Debug' + } elseif ($Request.Query.ListAll) { + $ExcludedTenants = Get-CIPPAzDataTableEntity @TenantsTable -Filter "PartitionKey eq 'Tenants'" | Sort-Object -Property displayName + Write-LogMessage -API $APIName -headers $Headers -message 'got excluded tenants list' -Sev 'Debug' $body = @($ExcludedTenants) } try { # Interact with query parameters or the body of the request. - $name = $Request.Query.TenantFilter + $Name = $Request.Query.tenantFilter if ($Request.Query.AddExclusion) { $Tenants = Get-Tenants -IncludeAll | Where-Object { $Request.body.value -contains $_.customerId } $Excluded = foreach ($Tenant in $Tenants) { $Tenant.Excluded = $true - $Tenant.ExcludeUser = $username - $Tenant.ExcludeDate = $date + $Tenant.ExcludeUser = $Username + $Tenant.ExcludeDate = $Date $Tenant } Update-AzDataTableEntity -Force @TenantsTable -Entity ([pscustomobject]$Excluded) - Write-LogMessage -API $APINAME -tenant $($name) -headers $Request.Headers -message "Added exclusion for customer(s): $($Excluded.defaultDomainName -join ',')" -Sev 'Info' + Write-LogMessage -API $APIName -tenant $($Name) -headers $Headers -message "Added exclusion for customer(s): $($Excluded.defaultDomainName -join ',')" -Sev 'Info' $body = [pscustomobject]@{'Results' = "Success. Added exclusions for customer(s): $($Excluded.defaultDomainName -join ',')" } } @@ -51,12 +55,13 @@ Function Invoke-ExecExcludeTenant { $Tenant.ExcludeDate = '' Update-AzDataTableEntity -Force @TenantsTable -Entity $Tenant } - Write-LogMessage -API $APINAME -tenant $($name) -headers $Request.Headers -message "Removed exclusion for customer $($name)" -Sev 'Info' - $body = [pscustomobject]@{'Results' = "Success. We've removed $name from the excluded tenants." } + Write-LogMessage -API $APIName -tenant $($Name) -headers $Headers -message "Removed exclusion for customer $($Name)" -Sev 'Info' + $body = [pscustomobject]@{'Results' = "Success. We've removed $Name from the excluded tenants." } } } catch { - Write-LogMessage -API $APINAME -tenant $($name) -headers $Request.Headers -message "Exclusion API failed. $($_.Exception.Message)" -Sev 'Error' - $body = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" } + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API $APIName -tenant $($Name) -headers $Headers -message "Exclusion API failed. $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage + $body = [pscustomobject]@{'Results' = "Failed. $($ErrorMessage.NormalizedError)" } } if (!$body) { $body = @() } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecMaintenanceScripts.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecMaintenanceScripts.ps1 index c78ba5176232..42eeded7c863 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecMaintenanceScripts.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecMaintenanceScripts.ps1 @@ -11,7 +11,8 @@ Function Invoke-ExecMaintenanceScripts { 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 { $GraphToken = Get-GraphToken -returnRefresh $true $AccessTokenDetails = Read-JwtAccessDetails -Token $GraphToken.access_token diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecNotificationConfig.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecNotificationConfig.ps1 index 77a1ac8ae164..8436f9152a1f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecNotificationConfig.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecNotificationConfig.ps1 @@ -11,11 +11,11 @@ Function Invoke-ExecNotificationConfig { 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.' $sev = ([pscustomobject]$Request.body.Severity).value -join (',') $results = try { $Table = Get-CIPPTable -TableName SchedulerConfig diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecPasswordConfig.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecPasswordConfig.ps1 index b237e5fd15c7..cfe09ce96841 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecPasswordConfig.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecPasswordConfig.ps1 @@ -11,13 +11,13 @@ Function Invoke-ExecPasswordConfig { 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 Settings $PasswordType = (Get-CIPPAzDataTableEntity @Table) - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + $results = try { if ($Request.Query.List) { @{ passwordType = $PasswordType.passwordType } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecRestoreBackup.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecRestoreBackup.ps1 index e243f4ab2e0c..9a12d734adce 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecRestoreBackup.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecRestoreBackup.ps1 @@ -11,7 +11,8 @@ Function Invoke-ExecRestoreBackup { 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 { if ($Request.Body.BackupName -like 'CippBackup_*') { 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 11738d58737a..c9ec1f5bec39 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 @@ -52,16 +52,16 @@ Function Invoke-ExecSAMSetup { if ($env:MSI_SECRET) { Disable-AzContextAutosave -Scope Process | Out-Null $null = Connect-AzAccount -Identity - $SubscriptionId = $ENV:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 + $SubscriptionId = $env:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 $null = Set-AzContext -SubscriptionId $SubscriptionId } } - if (!$ENV:SetFromProfile) { + if (!$env:SetFromProfile) { Write-Information "We're reloading from KV" Get-CIPPAuthentication } - $KV = $ENV:WEBSITE_DEPLOYMENT_ID + $KV = $env:WEBSITE_DEPLOYMENT_ID $Table = Get-CIPPTable -TableName SAMWizard $Rows = Get-CIPPAzDataTableEntity @Table | Where-Object -Property Timestamp -GT (Get-Date).AddMinutes(-10) @@ -88,16 +88,16 @@ Function Invoke-ExecSAMSetup { if ($Request.Query.code) { try { $TenantId = $Rows.tenantid - if (!$TenantId -or $TenantId -eq 'NotStarted') { $TenantId = $ENV:TenantID } + if (!$TenantId -or $TenantId -eq 'NotStarted') { $TenantId = $env:TenantID } $AppID = $Rows.appid - if (!$AppID -or $AppID -eq 'NotStarted') { $appid = $ENV:ApplicationID } + if (!$AppID -or $AppID -eq 'NotStarted') { $appid = $env:ApplicationID } $URL = ($Request.headers.'x-ms-original-url').split('?') | Select-Object -First 1 if ($env:AzureWebJobsStorage -eq 'UseDevelopmentStorage=true') { $clientsecret = $Secret.ApplicationSecret } else { $clientsecret = Get-AzKeyVaultSecret -VaultName $kv -Name 'ApplicationSecret' -AsPlainText } - if (!$clientsecret) { $clientsecret = $ENV:ApplicationSecret } + if (!$clientsecret) { $clientsecret = $env:ApplicationSecret } Write-Information "client_id=$appid&scope=https://graph.microsoft.com/.default+offline_access+openid+profile&code=$($Request.Query.code)&grant_type=authorization_code&redirect_uri=$($url)&client_secret=$clientsecret" #-Uri "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token" $RefreshToken = Invoke-RestMethod -Method POST -Body "client_id=$appid&scope=https://graph.microsoft.com/.default+offline_access+openid+profile&code=$($Request.Query.code)&grant_type=authorization_code&redirect_uri=$($url)&client_secret=$clientsecret" -Uri "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token" -ContentType 'application/x-www-form-urlencoded' diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecMailboxMobileDevices.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecMailboxMobileDevices.ps1 index 2d54ba0aff50..378ff2d92529 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecMailboxMobileDevices.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecMailboxMobileDevices.ps1 @@ -11,7 +11,8 @@ Function Invoke-ExecMailboxMobileDevices { 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/Administration/Invoke-ExecSetLitigationHold.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecSetLitigationHold.ps1 new file mode 100644 index 000000000000..de8c459fe1fd --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecSetLitigationHold.ps1 @@ -0,0 +1,58 @@ +function Invoke-ExecSetLitigationHold { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.Mailbox.ReadWrite + #> + [CmdletBinding()] + 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.Body.tenantFilter + $LitHoldState = -not $Request.Body.disable -as [bool] + $Identity = $Request.Body.Identity + $UserPrincipalName = $Request.Body.UPN + $Days = $Request.Body.days -as [int] + + # Set the parameters for the EXO request + $ExoRequest = @{ + tenantid = $TenantFilter + cmdlet = 'Set-Mailbox' + cmdParams = @{ + Identity = $Identity + LitigationHoldEnabled = $LitHoldState + } + } + + # Add the duration of the hold if specified + if ($Days -ne 0 -and $LitHoldState -eq $true) { + $ExoRequest.cmdParams['LitigationHoldDuration'] = $Days + } + + # Execute the EXO request + try { + $null = New-ExoRequest @ExoRequest + $Results = "Litigation hold for $UserPrincipalName with Id $Identity has been set to $LitHoldState" + if ($Days -ne 0 -and $LitHoldState -eq $true) { + $Results += " for $Days days" + } + Write-LogMessage -API $APIName -tenant $TenantFilter -message $Results -sev Info + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Results = "Could not set litigation hold for $UserPrincipalName with Id $Identity to $LitHoldState. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -API $APIName -tenant $TenantFilter -message $Results -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 = $Results } + }) +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecSetMailboxRule.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecSetMailboxRule.ps1 new file mode 100644 index 000000000000..1a747f8c6f81 --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecSetMailboxRule.ps1 @@ -0,0 +1,58 @@ +using namespace System.Net + +Function Invoke-ExecSetMailboxRule { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.Mailbox.ReadWrite + #> + [CmdletBinding()] + 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.Body.TenantFilter + $RuleName = $Request.Body.ruleName + $RuleId = $Request.Body.ruleId + $Username = $Request.Body.userPrincipalName + $Enable = $Request.Body.Enable -as [bool] + $Disable = $Request.Body.Disable -as [bool] + + + # Set the rule + $SetCIPPMailboxRuleParams = @{ + Username = $Username + TenantFilter = $TenantFilter + APIName = $APIName + Headers = $Headers + RuleId = $RuleId + RuleName = $RuleName + } + if ($Enable -eq $true) { + $SetCIPPMailboxRuleParams.Add('Enable', $true) + } elseif ($Disable -eq $true) { + $SetCIPPMailboxRuleParams.Add('Disable', $true) + } else { + Write-LogMessage -headers $Headers -API $APIName -message 'No state provided for mailbox rule' -Sev 'Error' -tenant $TenantFilter + throw 'No state provided for mailbox rule' + } + + $Results = Set-CIPPMailboxRule @SetCIPPMailboxRuleParams + + if ($Results -like '*Could not set*') { + $StatusCode = [HttpStatusCode]::InternalServerError + } else { + $StatusCode = [HttpStatusCode]::OK + } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @{ Results = $Results } + }) + +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListMailboxMobileDevices.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListMailboxMobileDevices.ps1 index 3e1be65549a6..9a4aff412881 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListMailboxMobileDevices.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListMailboxMobileDevices.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListMailboxMobileDevices { 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/Administration/Invoke-ListMailboxes.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListMailboxes.ps1 index 89111ef324c8..b3ac4aebd388 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListMailboxes.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListMailboxes.ps1 @@ -17,7 +17,7 @@ Function Invoke-ListMailboxes { # Interact with query parameters or the body of the request. $TenantFilter = $Request.Query.tenantFilter try { - $Select = 'id,ExchangeGuid,ArchiveGuid,UserPrincipalName,DisplayName,PrimarySMTPAddress,RecipientType,RecipientTypeDetails,EmailAddresses,WhenSoftDeleted,IsInactiveMailbox,ForwardingSmtpAddress,DeliverToMailboxAndForward,ForwardingAddress,HiddenFromAddressListsEnabled,ExternalDirectoryObjectId,MessageCopyForSendOnBehalfEnabled,MessageCopyForSentAsEnabled' + $Select = 'id,ExchangeGuid,ArchiveGuid,UserPrincipalName,DisplayName,PrimarySMTPAddress,RecipientType,RecipientTypeDetails,EmailAddresses,WhenSoftDeleted,IsInactiveMailbox,ForwardingSmtpAddress,DeliverToMailboxAndForward,ForwardingAddress,HiddenFromAddressListsEnabled,ExternalDirectoryObjectId,MessageCopyForSendOnBehalfEnabled,MessageCopyForSentAsEnabled,PersistedCapabilities,LitigationHoldEnabled,LitigationHoldDate,LitigationHoldDuration' $ExoRequest = @{ tenantid = $TenantFilter cmdlet = 'Get-Mailbox' @@ -69,7 +69,12 @@ Function Invoke-ListMailboxes { HiddenFromAddressListsEnabled, ExternalDirectoryObjectId, MessageCopyForSendOnBehalfEnabled, - MessageCopyForSentAsEnabled + MessageCopyForSentAsEnabled, + LitigationHoldEnabled, + LitigationHoldDate, + LitigationHoldDuration, + @{ Name = 'LicensedForLitigationHold'; Expression = { ($_.PersistedCapabilities -contains 'BPOS_S_DlpAddOn' -or $_.PersistedCapabilities -contains 'BPOS_S_Enterprise') } } + $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListSharedMailboxStatistics.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListSharedMailboxStatistics.ps1 index 96edbf15faeb..2e7f2041209c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListSharedMailboxStatistics.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListSharedMailboxStatistics.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListSharedMailboxStatistics { 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' # XXX Seems like an unused endpoint? -Bobby diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListmailboxPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListmailboxPermissions.ps1 index 449fc929541d..9b1c4f03cf0b 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListmailboxPermissions.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ListmailboxPermissions.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListmailboxPermissions { 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/Resources/Invoke-ListRoomLists.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-ListRoomLists.ps1 index bf4891463fa7..be10ef655ae7 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-ListRoomLists.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-ListRoomLists.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListRoomLists { 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/Resources/Invoke-ListRooms.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-ListRooms.ps1 index 916364ef0f6c..4507af02a40e 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-ListRooms.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-ListRooms.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListRooms { 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/Spamfilter/Invoke-EditSpamFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-EditSpamFilter.ps1 index 7559e53ab41c..c240cd6db65b 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-EditSpamFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-EditSpamFilter.ps1 @@ -11,7 +11,8 @@ Function Invoke-EditSpamFilter { 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 $Name = $Request.Query.name ?? $Request.Body.name diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ExecQuarantineManagement.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ExecQuarantineManagement.ps1 index 4421360709dc..3f2dc78cafa3 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ExecQuarantineManagement.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ExecQuarantineManagement.ps1 @@ -11,23 +11,26 @@ Function Invoke-ExecQuarantineManagement { 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. Try { - $TenantFilter = $Request.Body.tenantFilter + $TenantFilter = $Request.Body.tenantFilter | Select-Object -First 1 $params = @{ - Identity = $Request.Body.Identity AllowSender = [boolean]$Request.Body.AllowSender - ReleaseToAll = [boolean]$Request.Body.Type - ActionType = $Request.Body.Type + ReleaseToAll = $true + ActionType = ($Request.Body.Type | Select-Object -First 1) + } + if ($Request.Body.Identity -is [string]) { + $params['Identity'] = $Request.Body.Identity + } else { + $params['Identities'] = $Request.Body.Identity } - New-ExoRequest -tenantid $TenantFilter -cmdlet 'Release-QuarantineMessage' -cmdParams $Params $Results = [pscustomobject]@{'Results' = "Successfully processed $($Request.Body.Identity)" } Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $TenantFilter -message "Successfully processed Quarantine ID $($Request.Body.Identity)" -Sev 'Info' diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListConnectionFilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListConnectionFilter.ps1 index fb80de05afbd..82d6a7919596 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListConnectionFilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListConnectionFilter.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListConnectionFilter { 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/Email-Exchange/Spamfilter/Invoke-ListConnectionFilterTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListConnectionFilterTemplates.ps1 index b799ab74a6e1..ddca12e5b200 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListConnectionFilterTemplates.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListConnectionFilterTemplates.ps1 @@ -3,7 +3,7 @@ using namespace System.Net Function Invoke-ListConnectionFilterTemplates { <# .FUNCTIONALITY - Entrypoint + Entrypoint,AnyTenant .ROLE Exchange.ConnectionFilter.Read #> diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListSpamFilterTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListSpamFilterTemplates.ps1 index a74c9491e4af..f31053b3a991 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListSpamFilterTemplates.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListSpamFilterTemplates.ps1 @@ -3,7 +3,7 @@ using namespace System.Net Function Invoke-ListSpamFilterTemplates { <# .FUNCTIONALITY - Entrypoint + Entrypoint,AnyTenant .ROLE Exchange.SpamFilter.Read #> @@ -11,7 +11,8 @@ Function Invoke-ListSpamFilterTemplates { 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/Spamfilter/Invoke-ListSpamfilter.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListSpamfilter.ps1 index efa8a228914c..d73d6ec45066 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListSpamfilter.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Spamfilter/Invoke-ListSpamfilter.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListSpamfilter { 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/Email-Exchange/Tools/Invoke-ExecMailTest.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Tools/Invoke-ExecMailTest.ps1 index e537a7d6ebdc..eb12dae07b53 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Tools/Invoke-ExecMailTest.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Tools/Invoke-ExecMailTest.ps1 @@ -10,7 +10,8 @@ Function Invoke-ExecMailTest { 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/Tools/Invoke-ListMailboxRestores.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Tools/Invoke-ListMailboxRestores.ps1 index 1ffe8b543310..60b496ac2128 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Tools/Invoke-ListMailboxRestores.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Tools/Invoke-ListMailboxRestores.ps1 @@ -8,7 +8,8 @@ function Invoke-ListMailboxRestores { 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/Transport/Invoke-ListExConnectorTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-ListExConnectorTemplates.ps1 index cb302859f8db..6e879be76193 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-ListExConnectorTemplates.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-ListExConnectorTemplates.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListExConnectorTemplates { 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/Transport/Invoke-ListTransportRules.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-ListTransportRules.ps1 index aeb9f976be35..227bfd6fd8b8 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-ListTransportRules.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-ListTransportRules.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListTransportRules { 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/Email-Exchange/Transport/Invoke-ListTransportRulesTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-ListTransportRulesTemplates.ps1 index 867d316dc260..d9cd3b00eb61 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-ListTransportRulesTemplates.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Transport/Invoke-ListTransportRulesTemplates.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListTransportRulesTemplates { 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' $Templates = Get-ChildItem 'Config\*.TransportRuleTemplate.json' | ForEach-Object { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddChocoApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddChocoApp.ps1 index 34cfeb198291..9c7ed6fd384f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddChocoApp.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddChocoApp.ps1 @@ -11,33 +11,33 @@ Function Invoke-AddChocoApp { 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 'PowerShell HTTP trigger function processed a request.' - $ChocoApp = $request.body + $ChocoApp = $Request.Body $intuneBody = Get-Content 'AddChocoApp\choco.app.json' | ConvertFrom-Json - $assignTo = $Request.body.AssignTo + $AssignTo = $Request.Body.AssignTo $intuneBody.description = $ChocoApp.description - $intuneBody.displayName = $chocoapp.ApplicationName + $intuneBody.displayName = $ChocoApp.ApplicationName $intuneBody.installExperience.runAsAccount = if ($ChocoApp.InstallAsSystem) { 'system' } else { 'user' } $intuneBody.installExperience.deviceRestartBehavior = if ($ChocoApp.DisableRestart) { 'suppress' } else { 'allow' } - $intuneBody.installCommandLine = "powershell.exe -executionpolicy bypass .\Install.ps1 -InstallChoco -Packagename $($chocoapp.PackageName)" + $intuneBody.installCommandLine = "powershell.exe -ExecutionPolicy Bypass .\Install.ps1 -InstallChoco -Packagename $($ChocoApp.PackageName)" if ($ChocoApp.customrepo) { - $intuneBody.installCommandLine = $intuneBody.installCommandLine + " -CustomRepo $($chocoapp.CustomRepo)" + $intuneBody.installCommandLine = $intuneBody.installCommandLine + " -CustomRepo $($ChocoApp.CustomRepo)" } - $intuneBody.UninstallCommandLine = "powershell.exe -executionpolicy bypass .\Uninstall.ps1 -Packagename $($chocoapp.PackageName)" - $intunebody.detectionRules[0].path = "$($ENV:SystemDrive)\programdata\chocolatey\lib" - $intunebody.detectionRules[0].fileOrFolderName = "$($chocoapp.PackageName)" + $intuneBody.UninstallCommandLine = "powershell.exe -ExecutionPolicy Bypass .\Uninstall.ps1 -Packagename $($ChocoApp.PackageName)" + $intuneBody.detectionRules[0].path = "$($ENV:SystemDrive)\programdata\chocolatey\lib" + $intuneBody.detectionRules[0].fileOrFolderName = "$($ChocoApp.PackageName)" - $Tenants = $Request.body.selectedTenants.defaultDomainName - $Results = foreach ($Tenant in $tenants) { + $Tenants = $Request.Body.selectedTenants.defaultDomainName + $Results = foreach ($Tenant in $Tenants) { try { $CompleteObject = [PSCustomObject]@{ - tenant = $tenant - Applicationname = $ChocoApp.ApplicationName - assignTo = $assignTo - InstallationIntent = $request.body.InstallationIntent - IntuneBody = $intunebody + tenant = $Tenant + ApplicationName = $ChocoApp.ApplicationName + assignTo = $AssignTo + InstallationIntent = $Request.Body.InstallationIntent + IntuneBody = $intuneBody } | ConvertTo-Json -Depth 15 $Table = Get-CippTable -tablename 'apps' $Table.Force = $true @@ -47,14 +47,14 @@ Function Invoke-AddChocoApp { PartitionKey = 'apps' } "Successfully added Choco App for $($Tenant) to queue." - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $tenant -message "Successfully added Choco App $($intunebody.Displayname) to queue" -Sev 'Info' + Write-LogMessage -headers $Headers -API $APIName -tenant $Tenant -message "Successfully added Choco App $($intuneBody.DisplayName) to queue" -Sev 'Info' } catch { "Failed adding Choco App for $($Tenant) to queue" - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $tenant -message "Failed to add Chocolatey Application $($intunebody.Displayname) to queue" -Sev 'Error' + Write-LogMessage -headers $Headers -API $APIName -tenant $Tenant -message "Failed to add Chocolatey Application $($intuneBody.DisplayName) to queue" -Sev 'Error' } } - $body = [pscustomobject]@{'Results' = $results } + $body = [PSCustomObject]@{'Results' = $Results } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddMSPApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddMSPApp.ps1 index b5d055d24c1b..b3d4e927c74c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddMSPApp.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddMSPApp.ps1 @@ -11,64 +11,65 @@ Function Invoke-AddMSPApp { 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 'PowerShell HTTP trigger function processed a request.' - $RMMApp = $request.body - $assignTo = $Request.body.AssignTo + $RMMApp = $Request.Body + $AssignTo = $Request.Body.AssignTo $intuneBody = Get-Content "AddMSPApp\$($RMMApp.RMMName.value).app.json" | ConvertFrom-Json $intuneBody.displayName = $RMMApp.DisplayName - $Tenants = $request.body.selectedTenants - $Results = foreach ($Tenant in $tenants) { - $InstallParams = [pscustomobject]$RMMApp.params - switch ($rmmapp.RMMName.value) { + $Tenants = $Request.Body.selectedTenants + $Results = foreach ($Tenant in $Tenants) { + $InstallParams = [PSCustomObject]$RMMApp.params + switch ($RMMApp.RMMName.value) { 'datto' { - Write-Host 'test' - $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -URL $($InstallParams.DattoURL) -GUID $($InstallParams.DattoGUID."$($tenant.customerId)")" - $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1' + Write-Host 'Processing Datto installation' + $installCommandLine = "powershell.exe -ExecutionPolicy Bypass .\install.ps1 -URL $($InstallParams.DattoURL) -GUID $($InstallParams.DattoGUID."$($Tenant.customerId)")" + $uninstallCommandLine = 'powershell.exe -ExecutionPolicy Bypass .\uninstall.ps1' } 'ninja' { - $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -InstallParam $($RMMApp.PackageName)" - $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1' + Write-Host 'Processing Ninja installation' + $installCommandLine = "powershell.exe -ExecutionPolicy Bypass .\install.ps1 -InstallParam $($RMMApp.PackageName)" + $uninstallCommandLine = 'powershell.exe -ExecutionPolicy Bypass .\uninstall.ps1' } 'Huntress' { - $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -OrgKey $($InstallParams.Orgkey."$($tenant.customerId)") -acctkey $($InstallParams.AccountKey)" - $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\install.ps1 -Uninstall' + $installCommandLine = "powershell.exe -ExecutionPolicy Bypass .\install.ps1 -OrgKey $($InstallParams.Orgkey."$($Tenant.customerId)") -acctkey $($InstallParams.AccountKey)" + $uninstallCommandLine = 'powershell.exe -ExecutionPolicy Bypass .\install.ps1 -Uninstall' } 'Immybot' { - $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -url $($InstallParams.ClientURL."$($tenant.customerId)")" - $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1' + $installCommandLine = "powershell.exe -ExecutionPolicy Bypass .\install.ps1 -url $($InstallParams.ClientURL."$($tenant.customerId)")" + $UninstallCommandLine = 'powershell.exe -ExecutionPolicy Bypass .\uninstall.ps1' } 'syncro' { - $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -URL $($InstallParams.ClientURL."$($tenant.customerId)")" - $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1' + $installCommandLine = "powershell.exe -ExecutionPolicy Bypass .\install.ps1 -URL $($InstallParams.ClientURL."$($Tenant.customerId)")" + $uninstallCommandLine = 'powershell.exe -ExecutionPolicy Bypass .\uninstall.ps1' } 'NCentral' { - $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -InstallParam $($RMMApp.PackageName)" - $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1' + $installCommandLine = "powershell.exe -ExecutionPolicy Bypass .\install.ps1 -InstallParam $($RMMApp.PackageName)" + $uninstallCommandLine = 'powershell.exe -ExecutionPolicy Bypass .\uninstall.ps1' } 'automate' { - $installcommandline = "c:\windows\sysnative\windowspowershell\v1.0\powershell.exe -executionpolicy bypass .\install.ps1 -Server $($InstallParams.Server) -InstallerToken $($InstallParams.InstallerToken."$($tenant.customerId)") -LocationID $($InstallParams.LocationID."$($tenant.customerId)")" - $UninstallCommandLine = "c:\windows\sysnative\windowspowershell\v1.0\powershell.exe -executionpolicy bypass .\uninstall.ps1 -Server $($InstallParams.Server)" + $installCommandLine = "c:\windows\sysnative\windowspowershell\v1.0\powershell.exe -ExecutionPolicy Bypass .\install.ps1 -Server $($InstallParams.Server) -InstallerToken $($InstallParams.InstallerToken."$($Tenant.customerId)") -LocationID $($InstallParams.LocationID."$($Tenant.customerId)")" + $uninstallCommandLine = "c:\windows\sysnative\windowspowershell\v1.0\powershell.exe -ExecutionPolicy Bypass .\uninstall.ps1 -Server $($InstallParams.Server)" $DetectionScript = (Get-Content 'AddMSPApp\automate.detection.ps1' -Raw) -replace '##SERVER##', $InstallParams.Server $intuneBody.detectionRules[0].scriptContent = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($DetectionScript)) } 'cwcommand' { - $installcommandline = "powershell.exe -executionpolicy bypass .\install.ps1 -Url $($InstallParams.ClientURL."$($tenant.customerId)")" - $UninstallCommandLine = 'powershell.exe -executionpolicy bypass .\uninstall.ps1' + $installCommandLine = "powershell.exe -ExecutionPolicy Bypass .\install.ps1 -Url $($InstallParams.ClientURL."$($Tenant.customerId)")" + $uninstallCommandLine = 'powershell.exe -ExecutionPolicy Bypass .\uninstall.ps1' } } - $intuneBody.installCommandLine = $installcommandline - $intuneBody.UninstallCommandLine = $UninstallCommandLine + $intuneBody.installCommandLine = $installCommandLine + $intuneBody.UninstallCommandLine = $uninstallCommandLine try { $CompleteObject = [PSCustomObject]@{ - tenant = $tenant.defaultDomainName - Applicationname = $RMMApp.DisplayName - assignTo = $assignTo - IntuneBody = $intunebody + tenant = $Tenant.defaultDomainName + ApplicationName = $RMMApp.DisplayName + assignTo = $AssignTo + IntuneBody = $intuneBody type = 'MSPApp' MSPAppName = $RMMApp.RMMName.value } | ConvertTo-Json -Depth 15 @@ -81,15 +82,15 @@ Function Invoke-AddMSPApp { status = 'Not Deployed yet' } "Successfully added MSP App for $($Tenant.defaultDomainName) to queue. " - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $tenant.defaultDomainName -message "MSP Application $($intunebody.Displayname) added to queue" -Sev 'Info' + Write-LogMessage -headers $Headers -API $APIName -tenant $Tenant.defaultDomainName -message "MSP Application $($intuneBody.DisplayName) added to queue" -Sev 'Info' } catch { - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $tenant.defaultDomainName -message "Failed to add MSP Application $($intunebody.Displayname) to queue" -Sev 'Error' + Write-LogMessage -headers $Headers -API $APIName -tenant $Tenant.defaultDomainName -message "Failed to add MSP Application $($intuneBody.DisplayName) to queue" -Sev 'Error' "Failed to add MSP app for $($Tenant.defaultDomainName) to queue" } } - $body = [pscustomobject]@{'Results' = $results } + $body = [PSCustomObject]@{'Results' = $Results } # 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/Endpoint/Applications/Invoke-AddOfficeApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddOfficeApp.ps1 index f2162cf98ff7..51a30d74f9bf 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddOfficeApp.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddOfficeApp.ps1 @@ -11,7 +11,8 @@ Function Invoke-AddOfficeApp { 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' # Input bindings are passed in via param block. diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddStoreApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddStoreApp.ps1 index 960560e29b5e..e8e069a5dd40 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddStoreApp.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-AddStoreApp.ps1 @@ -11,12 +11,13 @@ Function Invoke-AddStoreApp { 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 'PowerShell HTTP trigger function processed a request.' - $WinGetApp = $request.body - if ($ChocoApp.InstallAsSystem) { 'system' } else { 'user' } + $WinGetApp = $Request.Body $assignTo = $Request.body.AssignTo + + if ($ChocoApp.InstallAsSystem) { 'system' } else { 'user' } $WinGetData = [ordered]@{ '@odata.type' = '#microsoft.graph.winGetApp' 'displayName' = "$($WinGetApp.ApplicationName)" @@ -29,13 +30,13 @@ Function Invoke-AddStoreApp { } $Tenants = $Request.body.selectedTenants.defaultDomainName - $Results = foreach ($Tenant in $tenants) { + $Results = foreach ($Tenant in $Tenants) { try { $CompleteObject = [PSCustomObject]@{ - tenant = $tenant - Applicationname = $WinGetApp.ApplicationName + tenant = $Tenant + ApplicationName = $WinGetApp.ApplicationName assignTo = $assignTo - InstallationIntent = $request.body.InstallationIntent + InstallationIntent = $Request.Body.InstallationIntent type = 'WinGet' IntuneBody = $WinGetData } | ConvertTo-Json -Depth 15 @@ -48,14 +49,14 @@ Function Invoke-AddStoreApp { status = 'Not Deployed yet' } "Successfully added Store App for $($Tenant) to queue." - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $tenant -message "Successfully added Store App $($intunebody.Displayname) to queue" -Sev 'Info' + Write-LogMessage -headers $Headers -API $APIName -tenant $tenant -message "Successfully added Store App $($IntuneBody.DisplayName) to queue" -Sev 'Info' } catch { - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $tenant -message "Failed to add Store App $($intunebody.Displayname) to queue" -Sev 'Error' - "Failed added Store App for $($Tenant) to queue" + Write-LogMessage -headers $Headers -API $APIName -tenant $tenant -message "Failed to add Store App $($IntuneBody.DisplayName) to queue" -Sev 'Error' + "Failed to add Store App for $($Tenant) to queue" } } - $body = [pscustomobject]@{'Results' = $results } + $body = [pscustomobject]@{'Results' = $Results } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ExecAssignApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ExecAssignApp.ps1 index 999161fe866b..807f153a700c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ExecAssignApp.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ExecAssignApp.ps1 @@ -11,11 +11,11 @@ Function Invoke-ExecAssignApp { 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApps.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApps.ps1 index 92c5e188f1aa..6fb8e46dc801 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApps.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Applications/Invoke-ListApps.ps1 @@ -11,11 +11,11 @@ Function Invoke-ListApps { 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddAPDevice.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddAPDevice.ps1 index c7e1943a3cf2..b63f3ae3f6b4 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddAPDevice.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddAPDevice.ps1 @@ -11,11 +11,11 @@ Function Invoke-AddAPDevice { 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.' $TenantFilter = (Get-Tenants | Where-Object { $_.defaultDomainName -eq $Request.body.TenantFilter.value }).customerId $GroupName = if ($Request.body.Groupname) { $Request.body.Groupname } else { (New-Guid).GUID } Write-Host $GroupName diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddAutopilotConfig.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddAutopilotConfig.ps1 index 3834d45e071e..5112dc52d091 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddAutopilotConfig.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddAutopilotConfig.ps1 @@ -11,11 +11,11 @@ Function Invoke-AddAutopilotConfig { 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.' # Input bindings are passed in via param block. $Tenants = $Request.body.selectedTenants.value diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddEnrollment.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddEnrollment.ps1 index 1656c5a69c59..b8f8a4c34fe2 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddEnrollment.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-AddEnrollment.ps1 @@ -11,11 +11,11 @@ Function Invoke-AddEnrollment { 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.' # Input bindings are passed in via param block. $Tenants = $Request.body.selectedTenants.value diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ExecRenameAPDevice.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ExecRenameAPDevice.ps1 new file mode 100644 index 000000000000..8bf8228949f3 --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ExecRenameAPDevice.ps1 @@ -0,0 +1,61 @@ +using namespace System.Net + +Function Invoke-ExecRenameAPDevice { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Endpoint.Autopilot.ReadWrite + #> + [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 + + + try { + $DeviceId = $Request.Body.deviceId + $SerialNumber = $Request.Body.serialNumber + $DisplayName = $Request.Body.displayName + + # Validation + if ($DisplayName.Length -gt 15) { + $ValidationError = 'Display name cannot exceed 15 characters.' + } elseif ($DisplayName -notmatch '^[a-zA-Z0-9-]+$') { + # This regex also implicitly checks for spaces + $ValidationError = 'Display name can only contain letters (a-z, A-Z), numbers (0-9), and hyphens (-).' + } elseif ($DisplayName -match '^\d+$') { + $ValidationError = 'Display name cannot consist solely of numbers.' + } + + if ($null -ne $ValidationError) { + $Result = "Validation failed: $ValidationError" + $StatusCode = [HttpStatusCode]::BadRequest + } else { + # Validation passed, proceed with Graph API call + $body = @{ + displayName = $DisplayName + } | ConvertTo-Json + + New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeviceIdentities/$($DeviceId)/UpdateDeviceProperties" -tenantid $TenantFilter -body $body -method POST | Out-Null + $Result = "Successfully renamed device '$($DeviceId)' with serial number '$($SerialNumber)' to '$($DisplayName)'" + Write-LogMessage -Headers $User -API $APINAME -message $Result -Sev Info + $StatusCode = [HttpStatusCode]::OK + } + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Could not rename device '$($DeviceId)' with serial number '$($SerialNumber)' to '$($DisplayName)'. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $User -API $APINAME -message $Result -Sev Error -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::BadRequest + } + + + # 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/Endpoint/Autopilot/Invoke-ExecSetAPDeviceGroupTag.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ExecSetAPDeviceGroupTag.ps1 new file mode 100644 index 000000000000..d4f44ee9a618 --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ExecSetAPDeviceGroupTag.ps1 @@ -0,0 +1,53 @@ +using namespace System.Net + +Function Invoke-ExecSetAPDeviceGroupTag { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Endpoint.Autopilot.ReadWrite + #> + [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 + + try { + $DeviceId = $Request.Body.deviceId + $SerialNumber = $Request.Body.serialNumber + $GroupTag = $Request.Body.groupTag + + # Validation - GroupTag can be empty, but if provided, validate it + if ($null -ne $GroupTag -and $GroupTag -ne '' -and $GroupTag.Length -gt 128) { + $ValidationError = 'Group tag cannot exceed 128 characters.' + } + + if ($null -ne $ValidationError) { + $Result = "Validation failed: $ValidationError" + $StatusCode = [HttpStatusCode]::BadRequest + } else { + # Validation passed, proceed with Graph API call + $body = @{ + groupTag = $GroupTag + } | ConvertTo-Json + + New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeviceIdentities/$($DeviceId)/UpdateDeviceProperties" -tenantid $TenantFilter -body $body -method POST | Out-Null + $Result = "Successfully updated group tag for device '$($DeviceId)' with serial number '$($SerialNumber)' to '$($GroupTag)'" + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev Info + $StatusCode = [HttpStatusCode]::OK + } + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Could not update group tag for device '$($DeviceId)' with serial number '$($SerialNumber)' to '$($GroupTag)'. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev Error -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::BadRequest + } + + # 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/Endpoint/Autopilot/Invoke-ListAPDevices.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ListAPDevices.ps1 index fed6abfc5b13..acf5d9574a53 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ListAPDevices.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ListAPDevices.ps1 @@ -11,11 +11,11 @@ Function Invoke-ListAPDevices { 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ListAutopilotconfig.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ListAutopilotconfig.ps1 index a4832e59e1c3..a9a7bfdc0717 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ListAutopilotconfig.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-ListAutopilotconfig.ps1 @@ -11,11 +11,11 @@ Function Invoke-ListAutopilotconfig { 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-RemoveAPDevice.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-RemoveAPDevice.ps1 index 839a5410bb22..172f7d8eb9f2 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-RemoveAPDevice.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Autopilot/Invoke-RemoveAPDevice.ps1 @@ -11,7 +11,8 @@ Function Invoke-RemoveAPDevice { 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 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 b355013cdb96..b2a0f4a714f2 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 @@ -11,7 +11,8 @@ Function Invoke-AddDefenderDeployment { 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' $Tenants = ($Request.body.selectedTenants).value if ('AllTenants' -in $Tenants) { $Tenants = (Get-Tenants -IncludeErrors).defaultDomainName } 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 67fcdae69680..985b60203f3d 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 @@ -11,7 +11,8 @@ Function Invoke-AddPolicy { 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' $Tenants = ($Request.Body.tenantFilter.value) if ('AllTenants' -in $Tenants) { $Tenants = (Get-Tenants).defaultDomainName } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-EditIntuneScript.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-EditIntuneScript.ps1 index 902e39cb3102..138c59f7a51b 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-EditIntuneScript.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-EditIntuneScript.ps1 @@ -1,48 +1,48 @@ -using namespace System.Net - -function Invoke-EditIntuneScript { - <# - .FUNCTIONALITY - Entrypoint - .ROLE - Endpoint.MEM.ReadWrite - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - $Headers = $Request.Headers - Write-LogMessage -Headers $Headers -API $APINAME -message 'Accessed this API' -Sev Debug - - $graphUrl = "https://graph.microsoft.com/beta" - switch($Request.Method) { - "GET" { - $parms = @{ - uri = "$graphUrl/deviceManagement/deviceManagementScripts/$($Request.Query.ScriptId)" - tenantid = $Request.Query.TenantFilter - } - - $intuneScript = New-GraphGetRequest @parms - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $intuneScript - }) - } - "PATCH" { - $parms = @{ - uri = "$graphUrl/deviceManagement/deviceManagementScripts/$($Request.Body.ScriptId)" - tenantid = $Request.Body.TenantFilter - body = $Request.Body.IntuneScript - } - $patchResult = New-GraphPOSTRequest @parms -type "PATCH" - $body = [pscustomobject]@{'Results' = $patchResult } - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $body - }) - } - "POST" { - Write-Output "Adding script" - } - } -} +using namespace System.Net + +function Invoke-EditIntuneScript { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Endpoint.MEM.ReadWrite + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -Headers $Headers -API $APINAME -message 'Accessed this API' -Sev Debug + + $graphUrl = "https://graph.microsoft.com/beta" + switch($Request.Method) { + "GET" { + $parms = @{ + uri = "$graphUrl/deviceManagement/deviceManagementScripts/$($Request.Query.ScriptId)" + tenantid = $Request.Query.TenantFilter + } + + $intuneScript = New-GraphGetRequest @parms + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $intuneScript + }) + } + "PATCH" { + $parms = @{ + uri = "$graphUrl/deviceManagement/deviceManagementScripts/$($Request.Body.ScriptId)" + tenantid = $Request.Body.TenantFilter + body = $Request.Body.IntuneScript + } + $patchResult = New-GraphPOSTRequest @parms -type "PATCH" + $body = [pscustomobject]@{'Results' = $patchResult } + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $body + }) + } + "POST" { + Write-Output "Adding script" + } + } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-EditPolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-EditPolicy.ps1 index aa987198a3ee..85a0572a77cf 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-EditPolicy.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-EditPolicy.ps1 @@ -11,7 +11,8 @@ Function Invoke-EditPolicy { 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.body.tenantid $ID = $request.body.groupid diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecDeviceAction.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecDeviceAction.ps1 index 5057a2d7470f..bb14abf9e099 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecDeviceAction.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ExecDeviceAction.ps1 @@ -11,7 +11,8 @@ Function Invoke-ExecDeviceAction { 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 Body parameters or the body of the request. diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListDefenderState.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListDefenderState.ps1 index fb4efd4a5906..c895f478c158 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListDefenderState.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListDefenderState.ps1 @@ -11,11 +11,11 @@ Function Invoke-ListDefenderState { 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' $StatusCode = [HttpStatusCode]::OK - # 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntunePolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntunePolicy.ps1 index dd44396c9b43..b9f5ed00b5d5 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntunePolicy.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntunePolicy.ps1 @@ -14,8 +14,7 @@ Function Invoke-ListIntunePolicy { 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntuneScript.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntuneScript.ps1 index e53611befd00..2919be6460f0 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntuneScript.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntuneScript.ps1 @@ -12,11 +12,9 @@ function Invoke-ListIntuneScript { $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 - Write-Host 'PowerShell HTTP trigger function processed a request.' - - $TenantFilter = $Request.Query.TenantFilter + $TenantFilter = $Request.Query.tenantFilter $Results = [System.Collections.Generic.List[System.Object]]::new() $BulkRequests = [PSCustomObject]@( diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntuneTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntuneTemplates.ps1 index dccba05425ef..518bc40a7ac8 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntuneTemplates.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-ListIntuneTemplates.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListIntuneTemplates { 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' $Imported = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq 'settings'" diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Reports/Invoke-ListDevices.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Reports/Invoke-ListDevices.ps1 index 79b0cd5cb55b..f049534f1a64 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Reports/Invoke-ListDevices.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/Reports/Invoke-ListDevices.ps1 @@ -11,11 +11,11 @@ Function Invoke-ListDevices { 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-AddGroupTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-AddGroupTemplate.ps1 index d237a83f5f0c..8977007c3b4f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-AddGroupTemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-AddGroupTemplate.ps1 @@ -10,7 +10,8 @@ Function Invoke-AddGroupTemplate { [CmdletBinding()] 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/Identity/Administration/Groups/Invoke-EditGroup.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-EditGroup.ps1 index 0a6dca8a6755..ada79c9ca21f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-EditGroup.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-EditGroup.ps1 @@ -9,7 +9,8 @@ function Invoke-EditGroup { 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' $Results = [System.Collections.Generic.List[string]]@() $userobj = $Request.body 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 70672eb22229..514e50a4d6a9 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 @@ -5,7 +5,8 @@ Function Invoke-ListGroupSenderAuthentication { 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/Identity/Administration/Groups/Invoke-ListGroupTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroupTemplates.ps1 index 75cf77e3b9db..ec9510183266 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroupTemplates.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroupTemplates.ps1 @@ -11,10 +11,10 @@ Function Invoke-ListGroupTemplates { 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.' Write-Host $Request.query.id #List new policies diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroups.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroups.ps1 index 7c6a35c5739b..8f7359353f4a 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroups.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroups.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListGroups { 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 $selectstring = "id,createdDateTime,displayName,description,mail,mailEnabled,mailNickname,resourceProvisioningOptions,securityEnabled,visibility,organizationId,onPremisesSamAccountName,membershipRule,grouptypes,onPremisesSyncEnabled,resourceProvisioningOptions,userPrincipalName&`$expand=members(`$select=userPrincipalName)" diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddUserBulk.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddUserBulk.ps1 index 0eb1ef8db5f4..afe3c9a5f4ea 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddUserBulk.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-AddUserBulk.ps1 @@ -72,7 +72,12 @@ function Invoke-AddUserBulk { $LicenseSkus = $AssignedLicenses.value ?? $AssignedLicenses | Where-Object { $_ -match $GuidPattern } if (($LicenseSkus | Measure-Object).Count -gt 0) { Write-Information "- Assigned licenses set to $(($AssignedLicenses.label ?? $AssignedLicenses) -join ', ')" - $UserBody.assignedLicenses = @($LicenseSkus) + $Licenses = foreach ($Sku in $LicenseSkus) { + [PSCustomObject]@{ + skuId = $Sku + } + } + $UserBody.assignedLicenses = @($Licenses) } } } 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 b1f00d4e91cd..22da8a7ff36b 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 @@ -29,8 +29,7 @@ Function Invoke-EditUser { $AddToGroups = $Request.body.AddToGroups $RemoveFromGroups = $Request.body.RemoveFromGroups - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + #Edit the user try { Write-Host "$([boolean]$UserObj.MustChangePass)" diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecBECRemediate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecBECRemediate.ps1 index 20927bbfa3ec..d647d7fc5dff 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecBECRemediate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecBECRemediate.ps1 @@ -11,63 +11,62 @@ Function Invoke-ExecBECRemediate { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $User = $Request.Headers + $Headers = $Request.Headers + Write-LogMessage -Headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - Write-LogMessage -Headers $User -API $APINAME -message 'Accessed this API' -Sev 'Debug' - Write-Host 'PowerShell HTTP trigger function processed a request.' - - $TenantFilter = $request.body.tenantfilter - $SuspectUser = $request.body.userid - $username = $request.body.username + $TenantFilter = $Request.Body.tenantFilter + $SuspectUser = $Request.Body.userid + $Username = $Request.Body.username Write-Host $TenantFilter Write-Host $SuspectUser $Results = try { $Step = 'Reset Password' - Set-CIPPResetPassword -UserID $username -tenantFilter $TenantFilter -APIName $APINAME -Headers $User + Set-CIPPResetPassword -UserID $Username -tenantFilter $TenantFilter -APIName $APIName -Headers $Headers $Step = 'Disable Account' - Set-CIPPSignInState -userid $username -AccountEnabled $false -tenantFilter $TenantFilter -APIName $APINAME -Headers $User + Set-CIPPSignInState -userid $Username -AccountEnabled $false -tenantFilter $TenantFilter -APIName $APIName -Headers $Headers $Step = 'Revoke Sessions' - Revoke-CIPPSessions -userid $SuspectUser -username $username -Headers $User -APIName $APINAME -tenantFilter $TenantFilter + Revoke-CIPPSessions -userid $SuspectUser -username $Username -Headers $Headers -APIName $APIName -tenantFilter $TenantFilter $Step = 'Remove MFA methods' - Remove-CIPPUserMFA -UserPrincipalName $username -TenantFilter $TenantFilter -Headers $User + Remove-CIPPUserMFA -UserPrincipalName $Username -TenantFilter $TenantFilter -Headers $Headers $Step = 'Disable Inbox Rules' - $Rules = New-ExoRequest -anchor $username -tenantid $TenantFilter -cmdlet 'Get-InboxRule' -cmdParams @{Mailbox = $username; IncludeHidden = $true } + $Rules = New-ExoRequest -anchor $Username -tenantid $TenantFilter -cmdlet 'Get-InboxRule' -cmdParams @{Mailbox = $Username; IncludeHidden = $true } $RuleDisabled = 0 $RuleFailed = 0 if (($Rules | Measure-Object).Count -gt 0) { $Rules | Where-Object { $_.Name -ne 'Junk E-Mail Rule' -and $_.Name -notlike 'Microsoft.Exchange.OOF.*' } | ForEach-Object { try { - $null = New-ExoRequest -anchor $username -tenantid $TenantFilter -cmdlet 'Disable-InboxRule' -cmdParams @{Confirm = $false; Identity = $_.Identity } - "Disabled Inbox Rule '$($_.Identity)' for $username" + $null = New-ExoRequest -anchor $Username -tenantid $TenantFilter -cmdlet 'Disable-InboxRule' -cmdParams @{Confirm = $false; Identity = $_.Identity } + "Disabled Inbox Rule '$($_.Identity)' for $Username" $RuleDisabled++ } catch { - "Failed to disable Inbox Rule '$($_.Identity)' for $username" + "Failed to disable Inbox Rule '$($_.Identity)' for $Username" $RuleFailed++ } } } if ($RuleDisabled -gt 0) { - "Disabled $RuleDisabled Inbox Rules for $username" + "Disabled $RuleDisabled Inbox Rules for $Username" } else { - "No Inbox Rules found for $username. We have not disabled any rules." + "No Inbox Rules found for $Username. We have not disabled any rules." } if ($RuleFailed -gt 0) { - "Failed to disable $RuleFailed Inbox Rules for $username" + "Failed to disable $RuleFailed Inbox Rules for $Username" } - - Write-LogMessage -API 'BECRemediate' -tenant $tenantfilter -message "Executed Remediation for $username" -sev 'Info' + $StatusCode = [HttpStatusCode]::OK + Write-LogMessage -API 'BECRemediate' -tenant $TenantFilter -message "Executed Remediation for $Username" -sev 'Info' } catch { $ErrorMessage = Get-CippException -Exception $_ - $results = [pscustomobject]@{'Results' = "Failed to execute remediation. $($ErrorMessage.NormalizedError)" } - Write-LogMessage -API 'BECRemediate' -tenant $tenantfilter -message "Executed Remediation for $username failed at the $Step step" -sev 'Error' -LogData $ErrorMessage + $Results = [pscustomobject]@{'Results' = "Failed to execute remediation. $($ErrorMessage.NormalizedError)" } + Write-LogMessage -API 'BECRemediate' -tenant $TenantFilter -message "Executed Remediation for $Username failed at the $Step step" -sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError } - $results = [pscustomobject]@{'Results' = @($Results) } + $Results = [pscustomobject]@{'Results' = @($Results) } # 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/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecCreateTAP.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecCreateTAP.ps1 index c4e205aaa480..8aed811cfd84 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 @@ -22,7 +22,7 @@ Function Invoke-ExecCreateTAP { $Result = New-CIPPTAP -userid $UserID -TenantFilter $TenantFilter -APIName $APIName -Headers $Headers $StatusCode = [HttpStatusCode]::OK } catch { - $Result = "$($_.Exception.Message)" + $Result = Get-NormalizedError -message $($_.Exception.Message) $StatusCode = [HttpStatusCode]::InternalServerError } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOneDriveShortCut.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOneDriveShortCut.ps1 index 7030dac2a4da..5da791680ea4 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOneDriveShortCut.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecOneDriveShortCut.ps1 @@ -11,7 +11,8 @@ Function Invoke-ExecOneDriveShortCut { 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 { $MessageResult = New-CIPPOneDriveShortCut -username $Request.Body.username -userid $Request.Body.userid -TenantFilter $Request.Body.tenantFilter -URL $Request.Body.siteUrl.value -Headers $Request.Headers 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 53f86a6975c5..11fed934022b 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 @@ -11,13 +11,14 @@ Function Invoke-ExecResetPass { 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 - $DisplayName = $Request.Query.displayName ?? $Request.Body.displayName + $DisplayName = $Request.Query.displayName ?? $Request.Body.displayName ?? $ID $MustChange = $Request.Query.MustChange ?? $Request.Body.MustChange $MustChange = [System.Convert]::ToBoolean($MustChange) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecRestoreDeleted.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecRestoreDeleted.ps1 index e2d85fae5706..b2c0ba22fb52 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecRestoreDeleted.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecRestoreDeleted.ps1 @@ -11,7 +11,8 @@ Function Invoke-ExecRestoreDeleted { 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 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 b09d8a09fa4b..822c6356dcf1 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 @@ -11,7 +11,8 @@ Function Invoke-ExecRevokeSessions { 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 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 e19d85d13d46..78b099d6eee6 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 @@ -11,7 +11,8 @@ function Invoke-ExecSendPush { 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 $UserEmail = $Request.body.UserEmail diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListPerUserMFA.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListPerUserMFA.ps1 index 7bc8db4c1fd7..7e6d040a18d9 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListPerUserMFA.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListPerUserMFA.ps1 @@ -14,8 +14,7 @@ function Invoke-ListPerUserMFA { $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.' + # Parse query parameters $Tenant = $Request.query.tenantFilter diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserConditionalAccessPolicies.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserConditionalAccessPolicies.ps1 index e2399fabe5c0..bd8ce3a7eb27 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserConditionalAccessPolicies.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserConditionalAccessPolicies.ps1 @@ -11,11 +11,11 @@ Function Invoke-ListUserConditionalAccessPolicies { 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserCounts.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserCounts.ps1 index fbbdde8aa359..f9522b7648a9 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserCounts.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserCounts.ps1 @@ -11,11 +11,11 @@ Function Invoke-ListUserCounts { 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserDevices.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserDevices.ps1 index 52e841377b01..d37bc6e836b2 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserDevices.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserDevices.ps1 @@ -11,11 +11,11 @@ Function Invoke-ListUserDevices { 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserGroups.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserGroups.ps1 index 870d2a755d48..88123afee17b 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserGroups.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserGroups.ps1 @@ -11,11 +11,11 @@ Function Invoke-ListUserGroups { 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxRules.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxRules.ps1 index a264dc39f8c6..74def3815f6d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxRules.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserMailboxRules.ps1 @@ -15,8 +15,7 @@ Function Invoke-ListUserMailboxRules { 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 { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserSettings.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserSettings.ps1 index 1ff0c7712939..858ddfb27da4 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserSettings.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserSettings.ps1 @@ -10,7 +10,8 @@ function Invoke-ListUserSettings { 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' $username = ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($request.headers.'x-ms-client-principal')) | ConvertFrom-Json).userDetails try { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserSigninLogs.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserSigninLogs.ps1 index 9df706720a68..a0009394dd72 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserSigninLogs.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ListUserSigninLogs.ps1 @@ -11,11 +11,11 @@ Function Invoke-ListUserSigninLogs { 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' $top = $Request.Query.top ? $Request.Query.top : 50 - # 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 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 a132268e8390..d2a5c2685bd3 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 @@ -11,7 +11,8 @@ Function Invoke-ListUsers { 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' $ConvertTable = Import-Csv ConversionTable.csv | Sort-Object -Property 'guid' -Unique # Interact with query parameters or the body of the request. diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecAlertsList.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecAlertsList.ps1 index 1ab2243b5b63..04f876786b21 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecAlertsList.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Security/Invoke-ExecAlertsList.ps1 @@ -43,6 +43,10 @@ Function Invoke-ExecAlertsList { } $DisplayableAlerts = New-FlatArray $AlertsObj | Where-Object { $null -ne $_.Id } | Sort-Object -Property EventDateTime -Descending + if (!$DisplayableAlerts) { + $DisplayableAlerts = @() + } + $Metadata = [PSCustomObject]@{} [PSCustomObject]@{ NewAlertsCount = $DisplayableAlerts | Where-Object { $_.Status -eq 'newAlert' } | Measure-Object | Select-Object -ExpandProperty Count @@ -51,7 +55,7 @@ Function Invoke-ExecAlertsList { SeverityMediumAlertsCount = $DisplayableAlerts | Where-Object { ($_.Status -eq 'inProgress') -or ($_.Status -eq 'newAlert') } | Where-Object { $_.Severity -eq 'medium' } | Measure-Object | Select-Object -ExpandProperty Count SeverityLowAlertsCount = $DisplayableAlerts | Where-Object { ($_.Status -eq 'inProgress') -or ($_.Status -eq 'newAlert') } | Where-Object { $_.Severity -eq 'low' } | Measure-Object | Select-Object -ExpandProperty Count SeverityInformationalCount = $DisplayableAlerts | Where-Object { ($_.Status -eq 'inProgress') -or ($_.Status -eq 'newAlert') } | Where-Object { $_.Severity -eq 'informational' } | Measure-Object | Select-Object -ExpandProperty Count - MSResults = $DisplayableAlerts + MSResults = @($DisplayableAlerts) } } else { $Table = Get-CIPPTable -TableName cachealertsandincidents diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-AddSite.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-AddSite.ps1 index be7dc4e714b3..e8f19acf0534 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-AddSite.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-AddSite.ps1 @@ -11,7 +11,8 @@ Function Invoke-AddSite { 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' $SharePointObj = $Request.body diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-AddSiteBulk.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-AddSiteBulk.ps1 index 049af0fbd648..8ca292b2c52f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-AddSiteBulk.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-AddSiteBulk.ps1 @@ -11,7 +11,8 @@ Function Invoke-AddSiteBulk { 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' $Results = [System.Collections.ArrayList]@() diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-AddTeam.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-AddTeam.ps1 index 6c00d43d4bb2..9f76c94071de 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-AddTeam.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-AddTeam.ps1 @@ -11,12 +11,12 @@ Function Invoke-AddTeam { 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' $userobj = $Request.body - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' + $Owners = ($userobj.owner) try { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecRemoveTeamsVoicePhoneNumberAssignment.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecRemoveTeamsVoicePhoneNumberAssignment.ps1 index 4af90af25044..b022aee68d46 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecRemoveTeamsVoicePhoneNumberAssignment.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecRemoveTeamsVoicePhoneNumberAssignment.ps1 @@ -11,7 +11,8 @@ Function Invoke-ExecRemoveTeamsVoicePhoneNumberAssignment { 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 try { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListSharepointQuota.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListSharepointQuota.ps1 index 233e0ba32654..d09419fcc476 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListSharepointQuota.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListSharepointQuota.ps1 @@ -11,10 +11,8 @@ Function Invoke-ListSharepointQuota { 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListSharepointSettings.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListSharepointSettings.ps1 index 5316c2cec66c..cb84b80a8b6e 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListSharepointSettings.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListSharepointSettings.ps1 @@ -11,11 +11,11 @@ Function Invoke-ListSharepointSettings { 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. $tenant = $Request.Query.TenantFilter diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeams.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeams.ps1 index 82acc236796f..38637679c79c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeams.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeams.ps1 @@ -11,11 +11,11 @@ Function Invoke-ListTeams { 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsActivity.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsActivity.ps1 index 426131cc047d..342f8096d272 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsActivity.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsActivity.ps1 @@ -11,8 +11,7 @@ Function Invoke-ListTeamsActivity { param($Request, $TriggerMetadata) - # 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsVoice.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsVoice.ps1 index 6e996b99c4fd..2bfd473f902c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsVoice.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListTeamsVoice.ps1 @@ -11,29 +11,30 @@ Function Invoke-ListTeamsVoice { 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 - $tenantid = (Get-Tenants | Where-Object -Property defaultDomainName -EQ $Request.Query.TenantFilter).customerId + $TenantFilter = $Request.Query.tenantFilter + $TenantId = (Get-Tenants | Where-Object -Property defaultDomainName -EQ $TenantFilter).customerId try { - $users = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`$top=999&`$select=id,userPrincipalName,displayName" -tenantid $TenantFilter) - $skip = 0 + $Users = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`$top=999&`$select=id,userPrincipalName,displayName" -tenantid $TenantFilter) + $Skip = 0 $GraphRequest = do { - Write-Host "Getting page $skip" - $data = (New-TeamsAPIGetRequest -uri "https://api.interfaces.records.teams.microsoft.com/Skype.TelephoneNumberMgmt/Tenants/$($Tenantid)/telephone-numbers?skip=$($skip)&locale=en-US&top=999" -tenantid $TenantFilter).TelephoneNumbers | ForEach-Object { + Write-Host "Getting page $Skip" + $data = (New-TeamsAPIGetRequest -uri "https://api.interfaces.records.teams.microsoft.com/Skype.TelephoneNumberMgmt/Tenants/$($TenantId)/telephone-numbers?skip=$($Skip)&locale=en-US&top=999" -tenantid $TenantFilter).TelephoneNumbers | ForEach-Object { Write-Host 'Reached the loop' $CompleteRequest = $_ | Select-Object *, @{Name = 'AssignedTo'; Expression = { $users | Where-Object -Property id -EQ $_.AssignedTo.id } } - $CompleteRequest.AcquisitionDate ? ($CompleteRequest.AcquisitionDate = $CompleteRequest.AcquisitionDate -split 'T' | Select-Object -First 1) : ($CompleteRequest | Add-Member -NotePropertyName 'AcquisitionDate' -NotePropertyValue 'Unknown' -Force) + if ($CompleteRequest.AcquisitionDate) { + $CompleteRequest.AcquisitionDate = $_.AcquisitionDate -split 'T' | Select-Object -First 1 + } else { + $CompleteRequest | Add-Member -NotePropertyName 'AcquisitionDate' -NotePropertyValue 'Unknown' -Force + } $CompleteRequest.AssignedTo ? $null : ($CompleteRequest | Add-Member -NotePropertyName 'AssignedTo' -NotePropertyValue 'Unassigned' -Force) $CompleteRequest } Write-Host 'Finished the loop' - $skip = $skip + 999 + $Skip = $Skip + 999 $Data } while ($data.Count -eq 999) Write-Host 'Exiting the Do.' diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-AddAlert.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-AddAlert.ps1 index 5288f805e25e..8fcf39248cd2 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-AddAlert.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-AddAlert.ps1 @@ -10,7 +10,8 @@ Function Invoke-AddAlert { [CmdletBinding()] 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' $Tenants = $request.body.tenantFilter $Conditions = $request.body.conditions | ConvertTo-Json -Compress -Depth 10 | Out-String $TenantsJson = $Tenants | ConvertTo-Json -Compress -Depth 10 | Out-String 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 3bbab76429c7..5cfc332f7ef8 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 @@ -33,7 +33,7 @@ Function Invoke-ListAlertsQueue { $TaskEntry = [PSCustomObject]@{ Tenants = @($Tenants.label) Conditions = $TranslatedConditions - excludedTenants = ($Task.excludedTenants | ConvertFrom-Json -Depth 10 -ErrorAction SilentlyContinue) + excludedTenants = @($Task.excludedTenants | ConvertFrom-Json -Depth 10 -ErrorAction SilentlyContinue) Actions = $TranslatedActions LogType = $Task.type EventType = 'Audit log Alert' @@ -64,10 +64,16 @@ Function Invoke-ListAlertsQueue { } foreach ($Task in $ScheduledTasks) { + if ($Task.excludedTenants) { + $ExcludedTenants = @($Task.excludedTenants) + } else { + $ExcludedTenants = @() + } + $TaskEntry = [PSCustomObject]@{ RowKey = $Task.RowKey PartitionKey = $Task.PartitionKey - excludedTenants = $Task.excludedTenants + excludedTenants = @($ExcludedTenants) Tenants = @($Task.Tenant) Conditions = $Task.Name Actions = $Task.PostExecution diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListWebhookAlert.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListWebhookAlert.ps1 index 7511b8c4e408..42c6bf3e8787 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListWebhookAlert.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListWebhookAlert.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListWebhookAlert { 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 'SchedulerConfig' $WebhookRow = foreach ($Webhook in Get-CIPPAzDataTableEntity @Table | Where-Object -Property PartitionKey -EQ 'WebhookAlert') { $Webhook.If = $Webhook.If | ConvertFrom-Json diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecAddMultiTenantApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecAddMultiTenantApp.ps1 index f7f661064f5c..b85e6bf5f9c2 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecAddMultiTenantApp.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecAddMultiTenantApp.ps1 @@ -10,7 +10,8 @@ function Invoke-ExecAddMultiTenantApp { 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' $DelegateResources = $request.body.permissions | Where-Object -Property origin -EQ 'Delegated' | ForEach-Object { @{ id = $_.id; type = 'Scope' } } $DelegateResourceAccess = @{ ResourceAppId = '00000003-0000-0000-c000-000000000000'; resourceAccess = $DelegateResources } $ApplicationResources = $request.body.permissions | Where-Object -Property origin -EQ 'Application' | ForEach-Object { @{ id = $_.id; type = 'Role' } } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecAppApproval.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecAppApproval.ps1 index 34ca07d3228a..26c9b127959e 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecAppApproval.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecAppApproval.ps1 @@ -11,10 +11,10 @@ Function Invoke-ExecAppApproval { 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.' Write-Host "$($Request.query.ID)" # Interact with query parameters or the body of the request. diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecAddSPN.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecAddSPN.ps1 index ce498176528c..45baf77621b4 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecAddSPN.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecAddSPN.ps1 @@ -11,13 +11,14 @@ Function Invoke-ExecAddSPN { 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. $Body = if ($Request.Query.Enable) { '{"accountEnabled":"true"}' } else { '{"accountEnabled":"false"}' } try { - $GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/v1.0/servicePrincipals' -tenantid $ENV:TenantID -type POST -Body "{ `"appId`": `"2832473f-ec63-45fb-976f-5d45a7d4bb91`" }" -NoAuthCheck $true - $Results = [pscustomobject]@{'Results' = "Successfully completed request. Add your GDAP migration permissions to your SAM application here: https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/CallAnAPI/appId/$($ENV:ApplicationID)/isMSAApp/ " } + $GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/v1.0/servicePrincipals' -tenantid $env:TenantID -type POST -Body "{ `"appId`": `"2832473f-ec63-45fb-976f-5d45a7d4bb91`" }" -NoAuthCheck $true + $Results = [pscustomobject]@{'Results' = "Successfully completed request. Add your GDAP migration permissions to your SAM application here: https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/CallAnAPI/appId/$($env:ApplicationID)/isMSAApp/ " } } catch { $Results = [pscustomobject]@{'Results' = "Failed to add SPN. Please manually execute 'New-AzureADServicePrincipal -AppId 2832473f-ec63-45fb-976f-5d45a7d4bb91' The error was $($_.Exception.Message)" } } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecOffboardTenant.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecOffboardTenant.ps1 index dc69176e989e..4afdfb601df5 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecOffboardTenant.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecOffboardTenant.ps1 @@ -122,7 +122,7 @@ Function Invoke-ExecOffboardTenant { # Remove multi-tenant apps with the CSP tenant as origin try { $multitenantCSPApps = (New-GraphGETRequest -Uri "https://graph.microsoft.com/v1.0/servicePrincipals?`$count=true&`$select=displayName,appId,id,appOwnerOrganizationId&`$filter=appOwnerOrganizationId eq $($env:TenantID)" -tenantid $Tenantfilter -ComplexFilter) - $sortedArray = $multitenantCSPApps | Sort-Object @{Expression = { if ($_.appId -eq $ENV:ApplicationID) { 1 } else { 0 } }; Ascending = $true } + $sortedArray = $multitenantCSPApps | Sort-Object @{Expression = { if ($_.appId -eq $env:ApplicationID) { 1 } else { 0 } }; Ascending = $true } $sortedArray | ForEach-Object { try { $delete = (New-GraphPostRequest -type 'DELETE' -Uri "https://graph.microsoft.com/v1.0/serviceprincipals/$($_.id)" -tenantid $Tenantfilter) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecUpdateSecureScore.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecUpdateSecureScore.ps1 index ec89669aefcc..406a029c49c4 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecUpdateSecureScore.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ExecUpdateSecureScore.ps1 @@ -11,7 +11,8 @@ Function Invoke-ExecUpdateSecureScore { 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. $Body = @{ diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListDomains.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListDomains.ps1 index 14b225267ec7..ece424ca883d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListDomains.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListDomains.ps1 @@ -11,11 +11,11 @@ Function Invoke-ListDomains { 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-EditTenant.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-EditTenant.ps1 index 3bc8d89e92cd..e100c89b8e2d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-EditTenant.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Tenant/Invoke-EditTenant.ps1 @@ -40,6 +40,7 @@ Function Invoke-EditTenant { } $null = Add-CIPPAzDataTableEntity @PropertiesTable -Entity $aliasEntity -Force Write-Host "Setting alias to $tenantAlias" + $Tenant | Add-Member -NotePropertyName 'originalDisplayName' -NotePropertyValue $tenant.displayName -Force $Tenant.displayName = $tenantAlias $null = Add-CIPPAzDataTableEntity @TenantTable -Entity $Tenant -Force } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddCAPolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddCAPolicy.ps1 index 1b7b990ecb1a..fc6fa8b523f3 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddCAPolicy.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddCAPolicy.ps1 @@ -11,19 +11,18 @@ Function Invoke-AddCAPolicy { 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' $Tenants = $Request.body.tenantFilter.value if ('AllTenants' -in $Tenants) { $Tenants = (Get-Tenants).defaultDomainName } $results = foreach ($Tenant in $tenants) { try { - $CAPolicy = New-CIPPCAPolicy -replacePattern $Request.body.replacename -Overwrite $request.body.overwrite -TenantFilter $tenant -state $request.body.NewState -RawJSON $Request.body.RawJSON -APIName $APIName -Headers $Request.Headers - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($Tenant) -message "Added Conditional Access Policy $($Displayname)" -Sev 'Info' - "Successfully added Conditional Access Policy for $($Tenant)" + $CAPolicy = New-CIPPCAPolicy -replacePattern $Request.Body.replacename -Overwrite $request.Body.overwrite -TenantFilter $Tenant -state $Request.Body.NewState -RawJSON $Request.Body.RawJSON -APIName $APIName -Headers $Headers + "$CAPolicy" } catch { - "Failed to add policy for $($Tenant): $($_.Exception.Message)" - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($Tenant) -message "Failed to add Conditional Access Policy $($Displayname). Error: $($_.Exception.Message)" -Sev 'Error' + "$($_.Exception.Message)" continue } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddCATemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddCATemplate.ps1 index 02200e39dc04..db7ca80c47bd 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddCATemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddCATemplate.ps1 @@ -11,12 +11,15 @@ Function Invoke-AddCATemplate { 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 + # Interact with query parameters or the body of the request. + $TenantFilter = $Request.Body.tenantFilter + $Name = $Request.Body.name try { $GUID = (New-Guid).GUID - $JSON = New-CIPPCATemplate -TenantFilter $TenantFilter -JSON $request.body + $JSON = New-CIPPCATemplate -TenantFilter $TenantFilter -JSON $Request.Body $Table = Get-CippTable -tablename 'templates' $Table.Force = $true Add-CIPPAzDataTableEntity @Table -Entity @{ @@ -25,19 +28,22 @@ Function Invoke-AddCATemplate { PartitionKey = 'CATemplate' GUID = "$GUID" } - Write-LogMessage -headers $Request.Headers -API $APINAME -message "Created CA Template $($Request.body.name) with GUID $GUID" -Sev 'Debug' - $body = [pscustomobject]@{'Results' = 'Successfully added template' } + $Result = "Created CA Template $($Name) with GUID $GUID" + Write-LogMessage -headers $Headers -API $APIName -message "Created CA Template $($Name) with GUID $GUID" -Sev 'Debug' + $StatusCode = [HttpStatusCode]::OK } catch { - Write-LogMessage -headers $Request.Headers -API $APINAME -message "Failed to create CA Template: $($_.Exception.Message)" -Sev 'Error' - $body = [pscustomobject]@{'Results' = "Intune Template Deployment failed: $($_.Exception.Message)" } + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed to create CA Template: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message "Failed to create CA Template: $($ErrorMessage.NormalizedError)" -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-AddNamedLocation.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddNamedLocation.ps1 index 538599a246ac..27831ac9c557 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddNamedLocation.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-AddNamedLocation.ps1 @@ -11,12 +11,10 @@ Function Invoke-AddNamedLocation { 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.' - # Input bindings are passed in via param block. $Tenants = $request.body.selectedTenants.value Write-Host ($Request.body | ConvertTo-Json) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCACheck.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCACheck.ps1 index 04a138b3f97f..b18528966f52 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCACheck.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCACheck.ps1 @@ -11,12 +11,13 @@ Function Invoke-ExecCaCheck { 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.body.tenantFilter - $UserID = $request.body.userId.value - if ($Request.body.IncludeApplications.value) { - $IncludeApplications = $Request.body.IncludeApplications.value + $Tenant = $Request.Body.tenantFilter + $UserID = $Request.Body.userID.value + if ($Request.Body.IncludeApplications.value) { + $IncludeApplications = $Request.Body.IncludeApplications.value } else { $IncludeApplications = '67ad5377-2d78-4ac2-a867-6300cda00e85' } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCAExclusion.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCAExclusion.ps1 index 003dd4e9a2b6..758b92eaef24 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCAExclusion.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCAExclusion.ps1 @@ -11,24 +11,34 @@ Function Invoke-ExecCAExclusion { 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 UserId is a guid, get the user's UPN - if ($Request.body.UserId -match '^[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}$') { - $Username = (New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/users/$($Request.body.UserId)" -tenantid $Request.body.TenantFilter).userPrincipalName + $TenantFilter = $Request.Body.tenantFilter + $UserId = $Request.Body.UserID + $EndDate = $Request.Body.EndDate + $PolicyId = $Request.Body.PolicyId + $ExclusionType = $Request.Body.ExclusionType + + + if ($UserId -match '^[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}$') { + $Username = (New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/users/$($UserId)" -tenantid $TenantFilter).userPrincipalName } - if ($Request.body.vacation -eq 'true') { - $StartDate = $Request.body.StartDate + if ($Request.Body.vacation -eq 'true') { + $StartDate = $Request.Body.StartDate + $EndDate = $Request.Body.EndDate $TaskBody = [pscustomobject]@{ - TenantFilter = $Request.body.TenantFilter - Name = "Add CA Exclusion Vacation Mode: $Username - $($Request.body.TenantFilter)" + TenantFilter = $TenantFilter + Name = "Add CA Exclusion Vacation Mode: $Username - $($TenantFilter)" Command = @{ value = 'Set-CIPPCAExclusion' label = 'Set-CIPPCAExclusion' } Parameters = [pscustomobject]@{ ExclusionType = 'Add' - UserID = $Request.body.UserID - PolicyId = $Request.body.PolicyId + UserID = $UserID + PolicyId = $PolicyId UserName = $Username } ScheduledTime = $StartDate @@ -36,12 +46,12 @@ Function Invoke-ExecCAExclusion { Add-CIPPScheduledTask -Task $TaskBody -hidden $false #Removal of the exclusion $TaskBody.Parameters.ExclusionType = 'Remove' - $TaskBody.Name = "Remove CA Exclusion Vacation Mode: $username - $($Request.body.TenantFilter)" - $TaskBody.ScheduledTime = $Request.body.EndDate + $TaskBody.Name = "Remove CA Exclusion Vacation Mode: $Username - $($TenantFilter)" + $TaskBody.ScheduledTime = $EndDate Add-CIPPScheduledTask -Task $TaskBody -hidden $false $body = @{ Results = "Successfully added vacation mode schedule for $Username." } } else { - Set-CIPPCAExclusion -TenantFilter $Request.body.TenantFilter -ExclusionType $Request.body.ExclusionType -UserID $Request.body.UserID -PolicyId $Request.body.PolicyId -Headers $Request.Headers -UserName $Username + Set-CIPPCAExclusion -TenantFilter $TenantFilter -ExclusionType $ExclusionType -UserID $UserID -PolicyId $PolicyId -Headers $Headers -UserName $Username } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecNamedLocation.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecNamedLocation.ps1 index 8cd1f2341fd4..f6eee67e208e 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecNamedLocation.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecNamedLocation.ps1 @@ -11,13 +11,11 @@ Function Invoke-ExecNamedLocation { 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.' - - $TenantFilter = $Request.Body.TenantFilter ?? $Request.Query.TenantFilter + $TenantFilter = $Request.Body.tenantFilter ?? $Request.Query.tenantFilter $NamedLocationId = $Request.Body.NamedLocationId ?? $Request.Query.NamedLocationId $change = $Request.Body.change ?? $Request.Query.change $content = $Request.Body.input ?? $Request.Query.input diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListCAtemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListCAtemplates.ps1 index b76cb67f4d8c..91a163298ce0 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListCAtemplates.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ListCAtemplates.ps1 @@ -3,7 +3,7 @@ using namespace System.Net Function Invoke-ListCAtemplates { <# .FUNCTIONALITY - Entrypoint + Entrypoint,AnyTenant .ROLE Tenant.ConditionalAccess.Read #> @@ -11,10 +11,10 @@ Function Invoke-ListCAtemplates { 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.' Write-Host $Request.query.id #Migrating old policies whenever you do a list $Table = Get-CippTable -tablename 'templates' 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 c96c3b99f044..d4c8fba42f9c 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,8 @@ Function Invoke-ListConditionalAccessPolicies { 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' function Get-LocationNameFromId { @@ -170,7 +171,7 @@ Function Invoke-ListConditionalAccessPolicies { id = $cap.id displayName = $cap.displayName customer = $cap.Customer - tenantID = $cap.TenantID + tenantID = $TenantFilter createdDateTime = $(if (![string]::IsNullOrEmpty($cap.createdDateTime)) { [datetime]$cap.createdDateTime } else { '' }) modifiedDateTime = $(if (![string]::IsNullOrEmpty($cap.modifiedDateTime)) { [datetime]$cap.modifiedDateTime }else { '' }) state = $cap.state diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-RemoveCAPolicy.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-RemoveCAPolicy.ps1 index 7c894788f257..335d8b654164 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-RemoveCAPolicy.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-RemoveCAPolicy.ps1 @@ -12,7 +12,7 @@ Function Invoke-RemoveCAPolicy { $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' # Interact with query parameters or the body of the request. $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-RemoveCATemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-RemoveCATemplate.ps1 index e800d423fc90..9113d01dd2cf 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-RemoveCATemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-RemoveCATemplate.ps1 @@ -12,9 +12,9 @@ Function Invoke-RemoveCATemplate { $APIName = $Request.Params.CIPPEndpoint $Headers = $Request.Headers - $ID = $request.Query.ID ?? $Request.Body.ID 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' diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecAddGDAPRole.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecAddGDAPRole.ps1 index 17d31de48761..8178ed55e47b 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecAddGDAPRole.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecAddGDAPRole.ps1 @@ -11,7 +11,8 @@ function Invoke-ExecAddGDAPRole { 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' $Action = $Request.Body.Action ?? $Request.Query.Action ?? 'AddRoleSimple' $GroupBlockList = @('All Users', 'AdminAgents', 'HelpdeskAgents', 'SalesAgents') @@ -80,9 +81,9 @@ function Invoke-ExecAddGDAPRole { @{ label = 'Privileged Authentication Administrator'; value = '7be44c8a-adaf-4e2a-84d6-ab2649e08a13' } ) - $Groups = $Request.body.gdapRoles ?? $CippDefaults + $Groups = $Request.Body.gdapRoles ?? $CippDefaults - $CustomSuffix = $Request.body.customSuffix + $CustomSuffix = $Request.Body.customSuffix $Table = Get-CIPPTable -TableName 'GDAPRoles' $Results = [System.Collections.Generic.List[string]]::new() diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecAutoExtendGDAP.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecAutoExtendGDAP.ps1 index 75bdbd0bc4d2..b724655e023f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecAutoExtendGDAP.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecAutoExtendGDAP.ps1 @@ -10,6 +10,10 @@ Function Invoke-ExecAutoExtendGDAP { [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 ?? $Request.Body.ID $Results = Set-CIPPGDAPAutoExtend -RelationShipid $Id diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecDeleteGDAPRelationship.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecDeleteGDAPRelationship.ps1 index a6abd42ddf8d..e64d098aa5ef 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecDeleteGDAPRelationship.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecDeleteGDAPRelationship.ps1 @@ -11,14 +11,15 @@ Function Invoke-ExecDeleteGDAPRelationship { 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. $GDAPID = $Request.Query.GDAPId ?? $Request.Body.GDAPId try { $DELETE = New-GraphPostRequest -NoAuthCheck $True -uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships/$($GDAPID)/requests" -type POST -body '{"action":"terminate"}' -tenantid $env:TenantID $Results = [pscustomobject]@{'Results' = "Success. GDAP relationship for $($GDAPID) been revoked" } - Write-LogMessage -headers $Request.Headers -API $APINAME -message "Success. GDAP relationship for $($GDAPID) been revoked" -Sev 'Info' + Write-LogMessage -headers $Headers -API $APIName -message "Success. GDAP relationship for $($GDAPID) been revoked" -Sev 'Info' } catch { $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecDeleteGDAPRoleMapping.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecDeleteGDAPRoleMapping.ps1 index c3149bbc49b4..39dad0529337 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecDeleteGDAPRoleMapping.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecDeleteGDAPRoleMapping.ps1 @@ -11,16 +11,18 @@ Function Invoke-ExecDeleteGDAPRoleMapping { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - $Table = Get-CIPPTable -TableName 'GDAPRoles' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + $Table = Get-CIPPTable -TableName 'GDAPRoles' $GroupId = $Request.Query.GroupId ?? $Request.Body.GroupId try { $Filter = "PartitionKey eq 'Roles' and RowKey eq '{0}'" -f $GroupId $Entity = Get-CIPPAzDataTableEntity @Table -Filter $Filter Remove-AzDataTableEntity -Force @Table -Entity $Entity $Results = [pscustomobject]@{'Results' = 'Success. GDAP relationship mapping deleted' } - Write-LogMessage -headers $Request.Headers -API $APINAME -message "GDAP relationship mapping deleted for $($GroupId)" -Sev 'Info' + Write-LogMessage -headers $Headers -API $APIName -message "GDAP relationship mapping deleted for $($GroupId)" -Sev 'Info' } catch { $Results = [pscustomobject]@{'Results' = "Failed. $($_.Exception.Message)" } 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 de85c8acf113..a2d36fbdd4f5 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 @@ -9,8 +9,9 @@ function Invoke-ExecGDAPInvite { [CmdletBinding()] param($Request, $TriggerMetadata) - $APIName = 'ExecGDAPInvite' - 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' $Action = $Request.Body.Action ?? $Request.Query.Action ?? 'Create' diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPInviteApproved.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPInviteApproved.ps1 index 15fbcfc52841..3f29d62ac3d1 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPInviteApproved.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPInviteApproved.ps1 @@ -10,7 +10,9 @@ Function Invoke-ExecGDAPInviteApproved { [CmdletBinding()] param($Request, $TriggerMetadata) - 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' Set-CIPPGDAPInviteGroups diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPRemoveGArole.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPRemoveGArole.ps1 index db74a5a08f23..35b7e8b4c647 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPRemoveGArole.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPRemoveGArole.ps1 @@ -9,7 +9,7 @@ Function Invoke-ExecGDAPRemoveGArole { [CmdletBinding()] param($Request, $TriggerMetadata) - $GDAPID = $request.query.GDAPId ?? $request.Body.GDAPId + $GDAPID = $Request.Query.GDAPId ?? $Request.Body.GDAPId try { $CheckActive = New-GraphGetRequest -NoAuthCheck $True -uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships/$($GDAPID)" -tenantid $env:TenantID diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPRoleTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPRoleTemplate.ps1 index 218d92780ff8..ec02efcf937d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPRoleTemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ExecGDAPRoleTemplate.ps1 @@ -10,6 +10,10 @@ Function Invoke-ExecGDAPRoleTemplate { [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 'GDAPRoleTemplates' $Templates = Get-CIPPAzDataTableEntity @Table 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 179c0c603aa5..5ad7f3d8d72d 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 @@ -11,7 +11,8 @@ Function Invoke-ListGDAPInvite { 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/Tenant/GDAP/Invoke-ListGDAPRoles.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPRoles.ps1 index 64f10cdbe9a1..4f615d67b329 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPRoles.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/GDAP/Invoke-ListGDAPRoles.ps1 @@ -11,11 +11,11 @@ Function Invoke-ListGDAPRoles { 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 'GDAPRoles' $Groups = Get-CIPPAzDataTableEntity @Table diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Reports/Invoke-ListLicenses.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Reports/Invoke-ListLicenses.ps1 index 59b8b8817d71..1fa957953f07 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Reports/Invoke-ListLicenses.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Reports/Invoke-ListLicenses.ps1 @@ -11,14 +11,12 @@ Function Invoke-ListLicenses { 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 $RawGraphRequest = if ($TenantFilter -ne 'AllTenants') { $GraphRequest = Get-CIPPLicenseOverview -TenantFilter $TenantFilter | ForEach-Object { $TermInfo = $_.TermInfo | ConvertFrom-Json -ErrorAction SilentlyContinue diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Reports/Invoke-ListOAuthApps.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Reports/Invoke-ListOAuthApps.ps1 index 4d720cdf9122..4eb7dc4e6188 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Reports/Invoke-ListOAuthApps.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Reports/Invoke-ListOAuthApps.ps1 @@ -11,15 +11,12 @@ Function Invoke-ListOAuthApps { 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 - if ($TenantFilter -eq 'AllTenants') { $Tenants = (Get-Tenants).defaultDomainName } else { $tenants = $TenantFilter } + if ($TenantFilter -eq 'AllTenants') { $Tenants = (Get-Tenants).defaultDomainName } else { $Tenants = $TenantFilter } try { $GraphRequest = foreach ($Tenant in $Tenants) { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Reports/Invoke-ListServiceHealth.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Reports/Invoke-ListServiceHealth.ps1 index 160533a5d1f9..9e707124ae8e 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Reports/Invoke-ListServiceHealth.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Reports/Invoke-ListServiceHealth.ps1 @@ -12,9 +12,10 @@ Function Invoke-ListServiceHealth { $APIName = $Request.Params.CIPPEndpoint $Headers = $Request.Headers - $TenantFilter = $Request.Query.tenantFilter 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 if ($TenantFilter -eq 'AllTenants') { $ResultHealthSummary = Get-Tenants | ForEach-Object -Parallel { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsDeploy.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsDeploy.ps1 index 7a8da437c4ad..b6646630d7bb 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsDeploy.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsDeploy.ps1 @@ -11,7 +11,8 @@ Function Invoke-AddStandardsDeploy { 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' $user = $request.headers.'x-ms-client-principal' $username = ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($user)) | ConvertFrom-Json).userDetails diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsTemplate.ps1 index 0c2bf8084f53..aa5027e259f4 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsTemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-AddStandardsTemplate.ps1 @@ -11,7 +11,8 @@ function Invoke-AddStandardsTemplate { 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 = $Request.body.GUID ? $request.body.GUID : (New-Guid).GUID #updatedBy = $request.headers.'x-ms-client-principal' diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-BestPracticeAnalyser_List.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-BestPracticeAnalyser_List.ps1 index c9cf3382971c..9f5dbd8c4858 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-BestPracticeAnalyser_List.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-BestPracticeAnalyser_List.ps1 @@ -11,7 +11,8 @@ Function Invoke-BestPracticeAnalyser_List { 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' $Tenants = Get-Tenants $Table = get-cipptable 'cachebpa' diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecBPA.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecBPA.ps1 index 9f40f4cdb9fe..a3484765099a 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecBPA.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecBPA.ps1 @@ -11,12 +11,14 @@ function Invoke-ExecBPA { $ConfigTable = Get-CIPPTable -tablename Config $Config = Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'OffloadFunctions' and RowKey eq 'OffloadFunctions'" + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + if ($Config -and $Config.state -eq $true) { if ($env:CIPP_PROCESSOR -ne 'true') { $Parameters = @{Force = $true } - if ($Request.Query.TenantFilter) { - $Parameters.TenantFilter = $Request.Query.TenantFilter - $RowKey = "Start-BPAOrchestrator-$($Request.Query.TenantFilter)" + if ($TenantFilter -and $TenantFilter -ne 'AllTenants') { + $Parameters.TenantFilter = $TenantFilter + $RowKey = "Start-BPAOrchestrator-$($TenantFilter)" } else { $RowKey = 'Start-BPAOrchestrator' } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecStandardConvert.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecStandardConvert.ps1 index ebc62316e6b3..a03765cad909 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecStandardConvert.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecStandardConvert.ps1 @@ -108,7 +108,7 @@ function Invoke-ExecStandardConvert { } else { $StdKey } $IsArrayStandard = ($NewStdKey -eq 'IntuneTemplate' -or $NewStdKey -eq 'ConditionalAccessTemplate') $ConvertedObj = Convert-SingleStandardItem $OldStd - if ($ConvertedObj -eq $null) { + if ($null -eq $ConvertedObj) { continue } @@ -173,7 +173,7 @@ function Invoke-ExecStandardConvert { $OldStandards = (Get-CIPPAzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json $AllTenantsStd = $OldStandards | Where-Object { $_.Tenant -eq 'AllTenants' } - $HasAllTenants = $AllTenantsStd -ne $null + $HasAllTenants = $null -ne $AllTenantsStd $AllTenantsExclusions = New-Object System.Collections.ArrayList $StandardsToConvert = New-Object System.Collections.ArrayList diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecStandardsRun.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecStandardsRun.ps1 index 735a6f98d219..f2440e006895 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecStandardsRun.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ExecStandardsRun.ps1 @@ -10,9 +10,12 @@ Function Invoke-ExecStandardsRun { [CmdletBinding()] param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - $tenantfilter = if ($Request.Query.TenantFilter) { $Request.Query.TenantFilter } else { 'allTenants' } - $TemplateId = if ($Request.Query.TemplateId) { $Request.Query.TemplateId } else { '*' } + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + + $TenantFilter = $Request.Query.tenantFilter ?? 'allTenants' + $TemplateId = $Request.Query.templateId ?? '*' $Table = Get-CippTable -tablename 'templates' $Filter = "PartitionKey eq 'StandardsTemplateV2'" $Templates = (Get-CIPPAzDataTableEntity @Table -Filter $Filter | Sort-Object TimeStamp).JSON | ForEach-Object { @@ -35,10 +38,10 @@ Function Invoke-ExecStandardsRun { $ProcessorFunction = [PSCustomObject]@{ PartitionKey = 'Function' - RowKey = "Invoke-CIPPStandardsRun-$tenantfilter" + RowKey = "Invoke-CIPPStandardsRun-$TenantFilter" FunctionName = 'Invoke-CIPPStandardsRun' Parameters = [string](ConvertTo-Json -Compress -InputObject @{ - TenantFilter = $tenantfilter + TenantFilter = $TenantFilter TemplateId = $TemplateId runManually = [bool]$Templates.runManually Force = $true @@ -46,20 +49,21 @@ Function Invoke-ExecStandardsRun { } $ProcessorQueue = Get-CIPPTable -TableName 'ProcessorQueue' Add-AzDataTableEntity @ProcessorQueue -Entity $ProcessorFunction -Force - $Results = "Successfully Queued Standards Run for Tenant $tenantfilter" + $Results = "Successfully Queued Standards Run for Tenant $TenantFilter" } } else { try { - $null = Invoke-CIPPStandardsRun -Tenantfilter $tenantfilter -TemplateID $TemplateId -runManually ([bool]$Templates.runManually) -Force - $Results = "Successfully Started Standards Run for Tenant $tenantfilter" - Write-LogMessage -tenant $tenantfilter -API $APINAME -message $Results -Sev 'Info' + $null = Invoke-CIPPStandardsRun -TenantFilter $TenantFilter -TemplateID $TemplateId -runManually ([bool]$Templates.runManually) -Force + $Results = "Successfully started Standards Run for tenant: $TenantFilter" + Write-LogMessage -headers $Headers -tenant $TenantFilter -API $APIName -message $Results -Sev 'Info' } catch { - $Results = "Failed to start standards run for $tenantfilter. Error: $($_.Exception.Message)" - Write-LogMessage -tenant $tenantfilter -API $APINAME -message $Results -Sev 'Error' + $ErrorMessage = Get-CippException -Exception $_ + $Results = "Failed to start standards run for tenant: $TenantFilter. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -tenant $TenantFilter -API $APIName -message $Results -Sev 'Error' -LogData $ErrorMessage } } - $Results = [pscustomobject]@{'Results' = "$results" } + $Results = [pscustomobject]@{'Results' = "$Results" } # 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/Standards/Invoke-ListBPA.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListBPA.ps1 index 65e7bd78bcf6..8e58e59058ab 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListBPA.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListBPA.ps1 @@ -11,11 +11,14 @@ Function Invoke-ListBPA { 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 'cachebpav2' - $name = $Request.query.Report - if ($name -eq $null) { $name = 'CIPP Best Practices v1.5 - Table view' } + # Interact with query parameters or the body of the request. + $TenantFilter = $Request.Query.tenantFilter + $Table = Get-CippTable 'cachebpav2' + $name = $Request.Query.Report + if ($null -eq $name) { $name = 'CIPP Best Practices v1.5 - Table view' } # Get all possible JSON files for reports, find the correct one, select the Columns $JSONFields = @() @@ -33,8 +36,8 @@ Function Invoke-ListBPA { } - if ($Request.query.tenantFilter -ne 'AllTenants' -and $Style -eq 'Tenant') { - $CustomerId = (Get-Tenants -TenantFilter $Request.query.tenantFilter).customerId + if ($TenantFilter -ne 'AllTenants' -and $Style -eq 'Tenant') { + $CustomerId = (Get-Tenants -TenantFilter $TenantFilter).customerId $mergedObject = New-Object pscustomobject $Data = (Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq '$CustomerId'") | ForEach-Object { $row = $_ @@ -83,9 +86,9 @@ Function Invoke-ListBPA { Columns = @($Columns) Keys = $Data | ForEach-Object { $_.PSObject.Properties | - Where-Object { $_.Name -ne 'PartitionKey' -and $_.Name -ne 'RowKey' -and $_.Name -ne 'Timestamp' } | - ForEach-Object { $_.Name } - } | Select-Object -Unique + Where-Object { $_.Name -ne 'PartitionKey' -and $_.Name -ne 'RowKey' -and $_.Name -ne 'Timestamp' } | + ForEach-Object { $_.Name } + } | Select-Object -Unique Style = $Style } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListBPATemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListBPATemplates.ps1 index d8f310af900d..c32e70d81ea9 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListBPATemplates.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListBPATemplates.ps1 @@ -11,9 +11,8 @@ Function Invoke-ListBPATemplates { 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' $Table = Get-CippTable -tablename 'templates' diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListDomainAnalyser.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListDomainAnalyser.ps1 index c644ea8eb38e..4cda61a033b9 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListDomainAnalyser.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListDomainAnalyser.ps1 @@ -11,7 +11,14 @@ Function Invoke-ListDomainAnalyser { [CmdletBinding()] param($Request, $TriggerMetadata) - $Results = Get-CIPPDomainAnalyser -TenantFilter $Request.Query.tenantFilter + $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 + + $Results = Get-CIPPDomainAnalyser -TenantFilter $TenantFilter # 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/Standards/Invoke-ListDomainHealth.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListDomainHealth.ps1 index 04916f6c449a..c080fe78c7fe 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListDomainHealth.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListDomainHealth.ps1 @@ -10,6 +10,10 @@ Function Invoke-ListDomainHealth { [CmdletBinding()] param($Request, $TriggerMetadata) + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + Import-Module DNSHealth try { @@ -38,10 +42,10 @@ Function Invoke-ListDomainHealth { $UserCreds = ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($request.headers.'x-ms-client-principal')) | ConvertFrom-Json) $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.' $StatusCode = [HttpStatusCode]::OK try { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListStandards.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListStandards.ps1 index a7a2d8358236..c4bbf2f79a6b 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListStandards.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListStandards.ps1 @@ -11,13 +11,18 @@ Function Invoke-ListStandards { 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 + if ($Request.Query.ShowConsolidated -eq $true) { $StandardQuery = @{ - TenantFilter = $Request.Query.TenantFilter + TenantFilter = $TenantFilter } - if ($Request.Query.TenantFilter -eq 'AllTenants') { + if ($TenantFilter -eq 'AllTenants') { $StandardQuery.ListAllTenants = $true } $CurrentStandards = @(Get-CIPPStandards @StandardQuery) @@ -26,20 +31,20 @@ Function Invoke-ListStandards { $Filter = "PartitionKey eq 'standards'" try { - if ($Request.query.TenantFilter) { - $tenants = (Get-CIPPAzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json -Depth 15 -ErrorAction Stop | Where-Object Tenant -EQ $Request.query.tenantFilter + if ($TenantFilter) { + $Tenants = (Get-CIPPAzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json -Depth 15 -ErrorAction Stop | Where-Object Tenant -EQ $TenantFilter } else { $Tenants = (Get-CIPPAzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json -Depth 15 -ErrorAction Stop } } catch {} - $CurrentStandards = foreach ($tenant in $tenants) { + $CurrentStandards = foreach ($tenant in $Tenants) { [PSCustomObject]@{ displayName = $tenant.tenant appliedBy = $tenant.addedBy appliedAt = $tenant.appliedAt standards = $tenant.Standards - StandardsExport = ($tenant.Standards.psobject.properties.name) -join ', ' + StandardsExport = ($tenant.Standards.PSObject.Properties.Name) -join ', ' } } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-RemoveBPATemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-RemoveBPATemplate.ps1 index f42e8242ddab..ebebb03ab3a9 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-RemoveBPATemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-RemoveBPATemplate.ps1 @@ -12,9 +12,9 @@ Function Invoke-RemoveBPATemplate { $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' - $ID = $request.Query.TemplateName ?? $request.Body.TemplateName + $ID = $Request.Query.TemplateName ?? $Request.Body.TemplateName try { $Table = Get-CippTable -tablename 'templates' diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-RemoveStandard.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-RemoveStandard.ps1 index 69b947300559..2a2347630687 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-RemoveStandard.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-RemoveStandard.ps1 @@ -11,29 +11,32 @@ Function Invoke-RemoveStandard { 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 + # Interact with query parameters or the body of the request. + $ID = $Request.Query.ID try { $Table = Get-CippTable -tablename 'standards' - $Filter = "PartitionKey eq 'standards' and RowKey eq '$id'" + $Filter = "PartitionKey eq 'standards' 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 for $ID." -Sev 'Info' + Remove-AzDataTableEntity -Force @Table -Entity $ClearRow + Write-LogMessage -Headers $Headers -API $APIName -message "Removed standards for $ID." -Sev 'Info' $body = [pscustomobject]@{'Results' = 'Successfully removed standards deployment' } + $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -Headers $User -API $APINAME -message "Failed to remove standard for $ID. $($ErrorMessage.NormalizedError)" -Sev 'Error' - $body = [pscustomobject]@{'Results' = 'Failed to remove standard)' } + Write-LogMessage -Headers $Headers -API $APIName -message "Failed to remove standard for $ID. $($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError + $body = [pscustomobject]@{'Results' = 'Failed to remove standard' } } # 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/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-RemoveStandardTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-RemoveStandardTemplate.ps1 index 956d58353988..74249b5bdec4 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-RemoveStandardTemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-RemoveStandardTemplate.ps1 @@ -14,6 +14,7 @@ Function Invoke-RemoveStandardTemplate { $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 ?? $Request.Query.ID try { $Table = Get-CippTable -tablename 'templates' diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-listStandardTemplates.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-listStandardTemplates.ps1 index 9af3e636cef8..3ebc2712adde 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-listStandardTemplates.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-listStandardTemplates.ps1 @@ -10,24 +10,30 @@ Function Invoke-listStandardTemplates { [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.Query.id + $Table = Get-CippTable -tablename 'templates' $Filter = "PartitionKey eq 'StandardsTemplateV2'" $Templates = (Get-CIPPAzDataTableEntity @Table -Filter $Filter) | ForEach-Object { $JSON = $_.JSON -replace '"Action":', '"action":' try { $RowKey = $_.RowKey - $data = $JSON | ConvertFrom-Json -Depth 100 -ErrorAction SilentlyContinue + $Data = $JSON | ConvertFrom-Json -Depth 100 -ErrorAction SilentlyContinue } catch { Write-Host "$($RowKey) standard could not be loaded: $($_.Exception.Message)" return } - $data | Add-Member -NotePropertyName 'GUID' -NotePropertyValue $_.GUID -Force - if ($data.excludedTenants) { $data.excludedTenants = @($data.excludedTenants) } - $data + $Data | Add-Member -NotePropertyName 'GUID' -NotePropertyValue $_.GUID -Force + if ($Data.excludedTenants) { $Data.excludedTenants = @($Data.excludedTenants) } + $Data } | Sort-Object -Property templateName - if ($Request.query.id) { $Templates = $Templates | Where-Object GUID -EQ $Request.query.id } + if ($ID) { $Templates = $Templates | Where-Object GUID -EQ $ID } # 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/Tenant/Tools/Invoke-AddBPATemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Tools/Invoke-AddBPATemplate.ps1 index 514473f084a6..04ed12a51fb6 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Tools/Invoke-AddBPATemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Tools/Invoke-AddBPATemplate.ps1 @@ -11,7 +11,8 @@ Function Invoke-AddBPATemplate { 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 { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Tools/Invoke-ExecGraphExplorerPreset.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Tools/Invoke-ExecGraphExplorerPreset.ps1 index de3d9e0614bf..4c87012301e0 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Tools/Invoke-ExecGraphExplorerPreset.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Tools/Invoke-ExecGraphExplorerPreset.ps1 @@ -11,8 +11,10 @@ Function Invoke-ExecGraphExplorerPreset { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - $Username = $request.headers.'x-ms-client-principal-name' + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + #UNDOREPLACE + $Username = ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Headers.'x-ms-client-principal')) | ConvertFrom-Json).userDetails $Action = $Request.Body.Action ?? '' diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tools/GitHub/Invoke-ExecCommunityRepo.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tools/GitHub/Invoke-ExecCommunityRepo.ps1 index 6cd0e4c3fec4..d30b00e19c09 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tools/GitHub/Invoke-ExecCommunityRepo.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tools/GitHub/Invoke-ExecCommunityRepo.ps1 @@ -107,7 +107,7 @@ function Invoke-ExecCommunityRepo { 'UploadTemplate' { $GUID = $Request.Body.GUID $TemplateTable = Get-CIPPTable -TableName templates - $TemplateEntity = Get-CIPPAzDataTableEntity @TemplateTable -Filter "RowKey eq '$($GUID)'" + $TemplateEntity = Get-CIPPAzDataTableEntity @TemplateTable -Filter "RowKey eq '$($GUID)'" | Select-Object -ExcludeProperty ETag, Timestamp $Branch = $RepoEntity.UploadBranch ?? $RepoEntity.DefaultBranch if ($TemplateEntity) { $Template = $TemplateEntity.JSON | ConvertFrom-Json diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecBreachSearch.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecBreachSearch.ps1 index efc70b91833f..f012ad7ec12e 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecBreachSearch.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecBreachSearch.ps1 @@ -11,8 +11,12 @@ Function Invoke-ExecBreachSearch { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug' - $TenantFilter = $Request.query.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. + $TenantFilter = $Request.query.tenantFilter + #Move to background job New-BreachTenantSearch -TenantFilter $TenantFilter Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecCSPLicense.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecCSPLicense.ps1 index 0ba09a9db3ee..652ccd0d6da8 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecCSPLicense.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecCSPLicense.ps1 @@ -11,11 +11,11 @@ Function Invoke-ExecCSPLicense { 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.Body.TenantFilter + $TenantFilter = $Request.Body.tenantFilter $Action = $Request.Body.Action $SKU = $Request.Body.SKU diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecExtensionNinjaOneQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecExtensionNinjaOneQueue.ps1 index 5ea8abad3067..1abf879ccc36 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecExtensionNinjaOneQueue.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecExtensionNinjaOneQueue.ps1 @@ -9,7 +9,9 @@ Function Invoke-ExecExtensionNinjaOneQueue { #> [CmdletBinding()] param($Request, $TriggerMetadata) - + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' Switch ($QueueItem.NinjaAction) { @@ -18,4 +20,13 @@ Function Invoke-ExecExtensionNinjaOneQueue { 'SyncTenant' { Invoke-NinjaOneTenantSync -QueueItem $QueueItem } } + $Body = [PSCustomObject]@{ + StatusCode = [HttpStatusCode]::OK + Body = 'Success' + } + + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $Body + }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecListAppId.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecListAppId.ps1 index 9036b16620b4..579a6f8f16fe 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecListAppId.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecListAppId.ps1 @@ -11,13 +11,14 @@ Function Invoke-ExecListAppId { param($Request, $TriggerMetadata) Get-CIPPAuthentication $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' $ResponseURL = "$(($Request.headers.'x-ms-original-url').replace('/api/ExecListAppId','/api/ExecSAMSetup'))" $Results = @{ - applicationId = $ENV:ApplicationID - tenantId = $ENV:TenantID - refreshUrl = "https://login.microsoftonline.com/$ENV:TenantID/oauth2/v2.0/authorize?client_id=$ENV:ApplicationID&response_type=code&redirect_uri=$ResponseURL&response_mode=query&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default+offline_access+profile+openid&state=1&prompt=select_account" + applicationId = $env:ApplicationID + tenantId = $env:TenantID + refreshUrl = "https://login.microsoftonline.com/$env:TenantID/oauth2/v2.0/authorize?client_id=$env:ApplicationID&response_type=code&redirect_uri=$ResponseURL&response_mode=query&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default+offline_access+profile+openid&state=1&prompt=select_account" } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSchedulerBillingRun.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSchedulerBillingRun.ps1 index 6c373d6deaf4..b0cfbff022f2 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSchedulerBillingRun.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSchedulerBillingRun.ps1 @@ -9,12 +9,17 @@ Function Invoke-ExecSchedulerBillingRun { #> [CmdletBinding()] param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + try { Write-LogMessage -API 'Scheduler_Billing' -tenant 'none' -message 'Starting billing processing.' -sev Info $Table = Get-CIPPTable -TableName Extensionsconfig $Configuration = (Get-CIPPAzDataTableEntity @Table).config | ConvertFrom-Json -Depth 10 - foreach ($ConfigItem in $Configuration.psobject.properties.name) { + foreach ($ConfigItem in $Configuration.PSObject.Properties.Name) { switch ($ConfigItem) { 'Gradient' { If ($Configuration.Gradient.enabled -and $Configuration.Gradient.BillingEnabled) { @@ -24,7 +29,7 @@ Function Invoke-ExecSchedulerBillingRun { } } } catch { - Write-LogMessage -API 'Scheduler_Billing' -tenant 'none' -message "Could not start billing processing $($_.Exception.Message)" -sev Error + Write-LogMessage -API 'Scheduler_Billing' -tenant 'none' -message "Could not start billing processing $($_.Exception.Message)" -sev Error -headers $Headers } } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSendOrgMessage.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSendOrgMessage.ps1 index ca89e41bd579..04c1b4b2ec12 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSendOrgMessage.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecSendOrgMessage.ps1 @@ -11,11 +11,11 @@ Function Invoke-ExecSendOrgMessage { 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUniversalSearch.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUniversalSearch.ps1 index e07781beb7f2..cc074c755c89 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUniversalSearch.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUniversalSearch.ps1 @@ -11,11 +11,11 @@ Function Invoke-ExecUniversalSearch { 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. diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUserSettings.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUserSettings.ps1 index ee1b63556b4d..c646fa7fdac1 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUserSettings.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecUserSettings.ps1 @@ -14,12 +14,13 @@ function Invoke-ExecUserSettings { 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 + $object = $Request.Body.currentSettings | Select-Object * -ExcludeProperty CurrentTenant, pageSizes, sidebarShow, sidebarUnfoldable, _persist | ConvertTo-Json -Compress -Depth 10 + $User = $Request.Body.user $Table = Get-CippTable -tablename 'UserSettings' $Table.Force = $true Add-CIPPAzDataTableEntity @Table -Entity @{ JSON = "$object" - RowKey = "$($Request.body.user)" + RowKey = "$User" PartitionKey = 'UserSettings' } $StatusCode = [HttpStatusCode]::OK diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAllTenantDeviceCompliance.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAllTenantDeviceCompliance.ps1 index 2db62cf8e0c3..496ed691952b 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAllTenantDeviceCompliance.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAllTenantDeviceCompliance.ps1 @@ -11,11 +11,11 @@ Function Invoke-ListAllTenantDeviceCompliance { 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAppStatus.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAppStatus.ps1 index baac00b5b28a..ba4f57322449 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAppStatus.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListAppStatus.ps1 @@ -11,11 +11,12 @@ Function Invoke-ListAppStatus { 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 $appFilter = $Request.Query.AppFilter Write-Host "Using $appFilter" $body = @" diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListBreachesAccount.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListBreachesAccount.ps1 index 4c9f894b3c4e..a9dbf181154e 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListBreachesAccount.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListBreachesAccount.ps1 @@ -11,12 +11,16 @@ Function Invoke-ListBreachesAccount { 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.account -like '*@*') { - $Results = Get-HIBPRequest "breachedaccount/$($Request.query.account)?truncateResponse=false" + # Interact with query parameters or the body of the request. + $Account = $Request.Query.account + + if ($Account -like '*@*') { + $Results = Get-HIBPRequest "breachedaccount/$($Account)?truncateResponse=false" } else { - $Results = Get-BreachInfo -Domain $Request.query.account + $Results = Get-BreachInfo -Domain $Account } # Associate values to output bindings by calling 'Push-OutputBinding'. diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListBreachesTenant.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListBreachesTenant.ps1 index 5e6104b3fdf3..4777f73f8aa8 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListBreachesTenant.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListBreachesTenant.ps1 @@ -11,9 +11,10 @@ Function Invoke-ListBreachesTenant { 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 + $TenantFilter = $Request.Query.tenantFilter $Table = Get-CIPPTable -TableName UserBreaches if ($TenantFilter -ne 'AllTenants') { diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCSPLicenses.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCSPLicenses.ps1 index ecbaecfc54df..a63225022d1f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCSPLicenses.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCSPLicenses.ps1 @@ -11,19 +11,24 @@ Function Invoke-ListCSPLicenses { 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 { - $GraphRequest = Get-SherwebCurrentSubscription -TenantFilter $Request.Query.TenantFilter + # Interact with query parameters or the body of the request. + $TenantFilter = $Request.Query.tenantFilter - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = @($GraphRequest) - }) -Clobber + try { + $Result = Get-SherwebCurrentSubscription -TenantFilter $TenantFilter + $StatusCode = [HttpStatusCode]::OK } catch { - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::BadRequest - Body = 'Unable to retrieve CSP licenses, ensure that you have enabled the Sherweb integration and mapped the tenant in the integration settings.' - }) -Clobber + $Result = 'Unable to retrieve CSP licenses, ensure that you have enabled the Sherweb integration and mapped the tenant in the integration settings.' + $StatusCode = [HttpStatusCode]::BadRequest } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = @($Result) + }) -Clobber + } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCSPsku.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCSPsku.ps1 index 2036ff01b2c6..dcf8fb9a523f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCSPsku.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListCSPsku.ps1 @@ -11,11 +11,15 @@ Function Invoke-ListCSPsku { 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 + $CurrentSkuOnly = $Request.Query.currentSkuOnly try { - if ($Request.Query.currentSkuOnly) { + if ($CurrentSkuOnly) { $GraphRequest = Get-SherwebCurrentSubscription -TenantFilter $TenantFilter } else { $GraphRequest = Get-SherwebCatalog -TenantFilter $TenantFilter diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDeviceDetails.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDeviceDetails.ps1 index 83dfbdaf9002..451212a6720b 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDeviceDetails.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListDeviceDetails.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListDeviceDetails { 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' # XXX Seems to be an unused endpoint? -Bobby diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExtensionsConfig.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExtensionsConfig.ps1 index 008ae6398f9e..0e71e7112ac1 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExtensionsConfig.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExtensionsConfig.ps1 @@ -3,7 +3,7 @@ using namespace System.Net Function Invoke-ListExtensionsConfig { <# .FUNCTIONALITY - Entrypoint + Entrypoint,AnyTenant .ROLE CIPP.Extension.Read #> @@ -11,7 +11,8 @@ Function Invoke-ListExtensionsConfig { 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 try { diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExternalTenantInfo.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExternalTenantInfo.ps1 index 3b8032de9946..52cc699df175 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExternalTenantInfo.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListExternalTenantInfo.ps1 @@ -11,19 +11,20 @@ Function Invoke-ListExternalTenantInfo { 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. - $Tenant = $request.query.tenant + $Tenant = $Request.Query.tenant + $TenantFilter = $Request.Query.tenantFilter # Normalize to tenantid and determine if tenant exists - $TenantId = (Invoke-RestMethod -Method GET "https://login.windows.net/$tenant/.well-known/openid-configuration").token_endpoint.Split('/')[3] + $TenantId = (Invoke-RestMethod -Method GET "https://login.windows.net/$Tenant/.well-known/openid-configuration").token_endpoint.Split('/')[3] if ($TenantId) { - $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/tenantRelationships/findTenantInformationByTenantId(tenantId='$TenantId')" -noauthcheck $true -tenantid $TenantFilter + $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/tenantRelationships/findTenantInformationByTenantId(tenantId='$TenantId')" -NoAuthCheck $true -tenantid $TenantFilter $StatusCode = [HttpStatusCode]::OK } @@ -52,17 +53,17 @@ Function Invoke-ListExternalTenantInfo { "@ # Create the headers - $headers = @{ + $AutoDiscoverHeaders = @{ 'Content-Type' = 'text/xml; charset=utf-8' 'SOAPAction' = '"http://schemas.microsoft.com/exchange/2010/Autodiscover/Autodiscover/GetFederationInformation"' 'User-Agent' = 'AutodiscoverClient' } # Invoke - $response = Invoke-RestMethod -UseBasicParsing -Method Post -Uri 'https://autodiscover-s.outlook.com/autodiscover/autodiscover.svc' -Body $body -Headers $headers + $Response = Invoke-RestMethod -UseBasicParsing -Method Post -Uri 'https://autodiscover-s.outlook.com/autodiscover/autodiscover.svc' -Body $body -Headers $AutoDiscoverHeaders # Return - $TenantDomains = $response.Envelope.body.GetFederationInformationResponseMessage.response.Domains.Domain | Sort-Object + $TenantDomains = $Response.Envelope.body.GetFederationInformationResponseMessage.response.Domains.Domain | Sort-Object } $results = [PSCustomObject]@{ diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionParameters.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionParameters.ps1 index d98a26b66eb0..3cf030a6a105 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionParameters.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionParameters.ps1 @@ -10,7 +10,8 @@ function Invoke-ListFunctionParameters { 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. $Module = $Request.Query.Module diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionStats.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionStats.ps1 index 9bcb80aca64e..7b0a103160cf 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionStats.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListFunctionStats.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListFunctionStats { 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 { $TenantFilter = $Request.Query.tenantFilter diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericTestFunction.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericTestFunction.ps1 index bb2172b2ec95..2d93efa37104 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericTestFunction.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGenericTestFunction.ps1 @@ -13,6 +13,7 @@ Function Invoke-ListGenericTestFunction { $APIName = $Request.Params.CIPPEndpoint $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]@{ diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphExplorerPresets.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphExplorerPresets.ps1 index 86153e7e1fc9..ee84bc74bc19 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphExplorerPresets.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphExplorerPresets.ps1 @@ -3,7 +3,7 @@ using namespace System.Net Function Invoke-ListGraphExplorerPresets { <# .FUNCTIONALITY - Entrypoint + Entrypoint,AnyTenant .ROLE CIPP.Core.Read #> @@ -11,7 +11,10 @@ Function Invoke-ListGraphExplorerPresets { 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. $Username = $Request.Headers['x-ms-client-principal-name'] try { diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListHaloClients.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListHaloClients.ps1 index 3d9397b985e4..b221ecab536e 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListHaloClients.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListHaloClients.ps1 @@ -11,12 +11,10 @@ Function Invoke-ListHaloClients { 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. try { $Table = Get-CIPPTable -TableName Extensionsconfig @@ -24,17 +22,18 @@ Function Invoke-ListHaloClients { $Token = Get-HaloToken -configuration $Configuration $i = 1 $RawHaloClients = do { - $Result = Invoke-RestMethod -Uri "$($Configuration.ResourceURL)/Client?page_no=$i&page_size=999&pageinate=true" -ContentType 'application/json' -Method GET -Headers @{Authorization = "Bearer $($token.access_token)" } + $Result = Invoke-RestMethod -Uri "$($Configuration.ResourceURL)/Client?page_no=$i&page_size=999&pageinate=true" -ContentType 'application/json' -Method GET -Headers @{Authorization = "Bearer $($Token.access_token)" } $Result.clients | Select-Object * -ExcludeProperty logo $i++ - $pagecount = [Math]::Ceiling($Result.record_count / 999) - } while ($i -le $pagecount) + $PageCount = [Math]::Ceiling($Result.record_count / 999) + } while ($i -le $PageCount) $HaloClients = $RawHaloClients | ForEach-Object { [PSCustomObject]@{ label = $_.name value = $_.id } } + Write-Host "Found $($HaloClients.Count) Halo Clients" $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIPWhitelist.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIPWhitelist.ps1 index bf031cfb22a8..8aa2cd88329b 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIPWhitelist.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIPWhitelist.ps1 @@ -10,11 +10,16 @@ Function Invoke-ListIPWhitelist { [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 'trustedIps' $body = Get-CIPPAzDataTableEntity @Table + # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK Body = @($body) }) -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntuneIntents.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntuneIntents.ps1 index 6e9d14f81319..8856eb60cc17 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntuneIntents.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListIntuneIntents.ps1 @@ -11,14 +11,12 @@ Function Invoke-ListIntuneIntents { 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 + try { $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/deviceManagement/Intents?`$expand=settings,categories" -tenantid $TenantFilter $StatusCode = [HttpStatusCode]::OK diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListKnownIPDb.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListKnownIPDb.ps1 index 0f666d3fce64..e05b3fc83065 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListKnownIPDb.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListKnownIPDb.ps1 @@ -11,13 +11,15 @@ Function Invoke-ListKnownIPDb { 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 - # Write to the Azure Functions log stream. - Write-Host 'PowerShell HTTP trigger function processed a request.' $Table = Get-CIPPTable -TableName 'knownlocationdbv2' - $Filter = "Tenant eq '$($Request.Query.TenantFilter)'" + $Filter = "Tenant eq '$($TenantFilter)'" $KnownIPDb = Get-CIPPAzDataTableEntity @Table -Filter $Filter # Associate values to output bindings by calling 'Push-OutputBinding'. diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListLogs.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListLogs.ps1 index c6fc0c2a88ac..34f4009c8d1d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListLogs.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListLogs.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListLogs { 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListNamedLocations.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListNamedLocations.ps1 index a683b78a8347..a89fcdff7068 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListNamedLocations.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListNamedLocations.ps1 @@ -11,11 +11,11 @@ Function Invoke-ListNamedLocations { 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 diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListNotificationConfig.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListNotificationConfig.ps1 index 4d991c9d466a..0017c80b4101 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListNotificationConfig.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListNotificationConfig.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListNotificationConfig { 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 SchedulerConfig $Filter = "RowKey eq 'CippNotifications' and PartitionKey eq 'CippNotifications'" diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListOrg.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListOrg.ps1 index e94737a79274..b7f08c601f60 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListOrg.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListOrg.ps1 @@ -11,16 +11,14 @@ Function Invoke-ListOrg { 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 if ($TenantFilter -eq 'AllTenants') { - + $GraphRequest = @() } else { $GraphRequest = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/organization' -tenantid $TenantFilter } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPartnerRelationships.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPartnerRelationships.ps1 index 927d63b7067e..2b95b674be96 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPartnerRelationships.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPartnerRelationships.ps1 @@ -11,29 +11,33 @@ Function Invoke-ListPartnerRelationships { 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 try { $GraphRequestList = @{ Endpoint = 'policies/crossTenantAccessPolicy/partners' - TenantFilter = $Request.Query.TenantFilter + TenantFilter = $TenantFilter QueueNameOverride = 'Partner Relationships' ReverseTenantLookup = $true } $GraphRequest = Get-GraphRequestList @GraphRequestList + $StatusCode = [HttpStatusCode]::OK } catch { $GraphRequest = @() + $StatusCode = [HttpStatusCode]::Forbidden } - $StatusCode = [HttpStatusCode]::OK - $results = [PSCustomObject]@{ + $Results = [PSCustomObject]@{ Results = @($GraphRequest) } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = $StatusCode - Body = $results + Body = $Results }) - } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPendingWebhooks.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPendingWebhooks.ps1 index e344ac10776e..78409b41c31f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPendingWebhooks.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPendingWebhooks.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListPendingWebhooks { 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 'WebhookIncoming' diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPotentialApps.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPotentialApps.ps1 index 0d95d6bffb71..56636a02deb0 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPotentialApps.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListPotentialApps.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListPotentialApps { 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.body.type -eq 'WinGet') { $body = @" @@ -20,8 +21,8 @@ Function Invoke-ListPotentialApps { $DataRequest = (Invoke-RestMethod -Uri 'https://storeedgefd.dsx.mp.microsoft.com/v9.0/manifestSearch' -Method POST -Body $body -ContentType 'Application/json').data | Select-Object @{l = 'applicationName'; e = { $_.packagename } }, @{l = 'packagename'; e = { $_.packageIdentifier } } | Sort-Object -Property applicationName } - if ($Request.body.type -eq 'Choco') { - $DataRequest = Invoke-RestMethod -Uri "https://community.chocolatey.org/api/v2/Search()?`$filter=IsLatestVersion&`$skip=0&`$top=999&searchTerm=%27$($request.body.SearchString)%27&targetFramework=%27%27&includePrerelease=false" -ContentType 'application/json' | Select-Object @{l = 'applicationName'; e = { $_.properties.Title } }, @{l = 'packagename'; e = { $_.title.'#text' } } | Sort-Object -Property applicationName + if ($Request.Body.type -eq 'Choco') { + $DataRequest = Invoke-RestMethod -Uri "https://community.chocolatey.org/api/v2/Search()?`$filter=IsLatestVersion&`$skip=0&`$top=999&searchTerm=%27$($Request.Body.SearchString)%27&targetFramework=%27%27&includePrerelease=false" -ContentType 'application/json' | Select-Object @{l = 'applicationName'; e = { $_.properties.Title } }, @{l = 'packagename'; e = { $_.title.'#text' } } | Sort-Object -Property applicationName } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRoles.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRoles.ps1 index 6d57f2daa1f9..612b4ecffd5d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRoles.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListRoles.ps1 @@ -11,20 +11,18 @@ Function Invoke-ListRoles { 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 $SelectList = 'id', 'displayName', 'userPrincipalName' [System.Collections.Generic.List[PSCustomObject]]$Roles = New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/directoryRoles?`$expand=members" -tenantid $TenantFilter $GraphRequest = foreach ($Role in $Roles) { - #[System.Collections.Generic.List[PSCustomObject]]$Members = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/directoryRoles/$($Role.id)/members?`$select=$($selectlist -join ',')" -tenantid $TenantFilter | Select-Object $SelectList + #[System.Collections.Generic.List[PSCustomObject]]$Members = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/directoryRoles/$($Role.id)/members?`$select=$($SelectList -join ',')" -tenantid $TenantFilter | Select-Object $SelectList $Members = if ($Role.members) { $role.members | ForEach-Object { " $($_.displayName) ($($_.userPrincipalName))" } } else { 'none' } [PSCustomObject]@{ DisplayName = $Role.displayName diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListTenantAllowBlockList.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListTenantAllowBlockList.ps1 index 84c536889682..13896c11c0d5 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListTenantAllowBlockList.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListTenantAllowBlockList.ps1 @@ -11,7 +11,8 @@ Function Invoke-ListTenantAllowBlockList { 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/Invoke-RemoveTenantAllowBlockList.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1 index 70b4d553949b..fab7f0297698 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-RemoveTenantAllowBlockList.ps1 @@ -11,11 +11,11 @@ Function Invoke-RemoveTenantAllowBlockList { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $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. + $TenantFilter = $Request.Body.tenantFilter $Entries = $Request.Body.Entries $ListType = $Request.Body.ListType diff --git a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-UpdatePermissionsOrchestrator.ps1 b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-UpdatePermissionsOrchestrator.ps1 index 599c57572ba0..10caa27d3383 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-UpdatePermissionsOrchestrator.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-UpdatePermissionsOrchestrator.ps1 @@ -10,9 +10,9 @@ function Start-UpdatePermissionsOrchestrator { Write-Information 'Updating Permissions' $PartnerTenant = @{ - 'customerId' = $env:TenantID + 'customerId' = $env:TenantID 'defaultDomainName' = 'PartnerTenant' - 'displayName' = '*Partner Tenant' + 'displayName' = '*Partner Tenant' } $TenantList = Get-Tenants -IncludeAll | Where-Object { $_.Excluded -eq $false } diff --git a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-UserTasksOrchestrator.ps1 b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-UserTasksOrchestrator.ps1 index 62810c4ab1dd..9863866fa438 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-UserTasksOrchestrator.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-UserTasksOrchestrator.ps1 @@ -21,7 +21,7 @@ function Start-UserTasksOrchestrator { PartitionKey = $task.PartitionKey RowKey = $task.RowKey ExecutedTime = "$currentUnixTime" - TaskState = 'Running' + TaskState = 'Planned' } $task.Parameters = $task.Parameters | ConvertFrom-Json -AsHashtable $task.AdditionalProperties = $task.AdditionalProperties | ConvertFrom-Json diff --git a/Modules/CIPPCore/Public/Entrypoints/Timer Functions/Start-CIPPStatsTimer.ps1 b/Modules/CIPPCore/Public/Entrypoints/Timer Functions/Start-CIPPStatsTimer.ps1 index f7c53265b9d9..e8d56975c448 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Timer Functions/Start-CIPPStatsTimer.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Timer Functions/Start-CIPPStatsTimer.ps1 @@ -9,7 +9,7 @@ function Start-CIPPStatsTimer { #We will never ship any data that is related to your instance, all we care about is the number of tenants, and the version of the API you are running, and if you completed setup. if ($PSCmdlet.ShouldProcess('Start-CIPPStatsTimer', 'Starting CIPP Stats Timer')) { - if ($ENV:ApplicationID -ne 'LongApplicationID') { + if ($env:ApplicationID -ne 'LongApplicationID') { $SetupComplete = $true } $TenantCount = (Get-Tenants -IncludeAll).count diff --git a/Modules/CIPPCore/Public/Entrypoints/Timer Functions/Start-TableCleanup.ps1 b/Modules/CIPPCore/Public/Entrypoints/Timer Functions/Start-TableCleanup.ps1 index ba15c02add60..de6d20e615d3 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(-1).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ'))'" + Filter = "PartitionKey eq 'Search' and Timestamp lt datetime'$((Get-Date).AddDays(-1).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ'))'" First = 10000 Property = @('PartitionKey', 'RowKey', 'ETag') } @@ -25,7 +25,7 @@ function Start-TableCleanup { @{ DataTableProps = @{ Context = (Get-CIPPTable -tablename 'CippFunctionStats').Context - Filter = "Timestamp lt datetime'$((Get-Date).AddDays(-7).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ'))'" + Filter = "PartitionKey eq 'Durable' and Timestamp lt datetime'$((Get-Date).AddDays(-7).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ'))'" First = 10000 Property = @('PartitionKey', 'RowKey', 'ETag') } @@ -33,7 +33,7 @@ function Start-TableCleanup { @{ DataTableProps = @{ Context = (Get-CIPPTable -tablename 'CippQueue').Context - Filter = "Timestamp lt datetime'$((Get-Date).AddDays(-7).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ'))'" + Filter = "PartitionKey eq 'CippQueue' and Timestamp lt datetime'$((Get-Date).AddDays(-7).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ'))'" First = 10000 Property = @('PartitionKey', 'RowKey', 'ETag') } @@ -41,7 +41,7 @@ function Start-TableCleanup { @{ DataTableProps = @{ Context = (Get-CIPPTable -tablename 'CippQueueTasks').Context - Filter = "Timestamp lt datetime'$((Get-Date).AddDays(-7).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ'))'" + Filter = "PartitionKey eq 'Task' and Timestamp lt datetime'$((Get-Date).AddDays(-7).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ'))'" First = 10000 Property = @('PartitionKey', 'RowKey', 'ETag') } @@ -61,7 +61,7 @@ function Start-TableCleanup { 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 $_) + #Write-LogMessage -API 'TableCleanup' -message "Failed to delete table $($Table.Context.TableName)" -sev Error -LogData (Get-CippException -Exception $_) } } } catch { diff --git a/Modules/CIPPCore/Public/Entrypoints/Timer Functions/Start-UpdateTokensTimer.ps1 b/Modules/CIPPCore/Public/Entrypoints/Timer Functions/Start-UpdateTokensTimer.ps1 index e065d4152245..3418faa6bff1 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Timer Functions/Start-UpdateTokensTimer.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Timer Functions/Start-UpdateTokensTimer.ps1 @@ -26,10 +26,10 @@ function Start-UpdateTokensTimer { if ($env:MSI_SECRET) { Disable-AzContextAutosave -Scope Process | Out-Null $null = Connect-AzAccount -Identity - $SubscriptionId = $ENV:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 + $SubscriptionId = $env:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 $null = Set-AzContext -SubscriptionId $SubscriptionId } - $KV = ($ENV:WEBSITE_DEPLOYMENT_ID -split '-')[0] + $KV = ($env:WEBSITE_DEPLOYMENT_ID -split '-')[0] if ($Refreshtoken) { Set-AzKeyVaultSecret -VaultName $KV -Name 'RefreshToken' -SecretValue (ConvertTo-SecureString -String $Refreshtoken -AsPlainText -Force) } else { diff --git a/Modules/CIPPCore/Public/Get-CIPPAuthentication.ps1 b/Modules/CIPPCore/Public/Get-CIPPAuthentication.ps1 index bb3cab727de7..e86fd4b2e128 100644 --- a/Modules/CIPPCore/Public/Get-CIPPAuthentication.ps1 +++ b/Modules/CIPPCore/Public/Get-CIPPAuthentication.ps1 @@ -15,19 +15,19 @@ function Get-CIPPAuthentication { } foreach ($Var in $Variables) { if ($Secret.$Var) { - Set-Item -Path ENV:$Var -Value $Secret.$Var -Force -ErrorAction Stop + Set-Item -Path env:$Var -Value $Secret.$Var -Force -ErrorAction Stop } } } else { Connect-AzAccount -Identity - $SubscriptionId = $ENV:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 + $SubscriptionId = $env:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 $null = Set-AzContext -SubscriptionId $SubscriptionId - $keyvaultname = ($ENV:WEBSITE_DEPLOYMENT_ID -split '-')[0] + $keyvaultname = ($env:WEBSITE_DEPLOYMENT_ID -split '-')[0] $Variables | ForEach-Object { - Set-Item -Path ENV:$_ -Value (Get-AzKeyVaultSecret -VaultName $keyvaultname -Name $_ -AsPlainText -ErrorAction Stop) -Force + Set-Item -Path env:$_ -Value (Get-AzKeyVaultSecret -VaultName $keyvaultname -Name $_ -AsPlainText -ErrorAction Stop) -Force } } - $ENV:SetFromProfile = $true + $env:SetFromProfile = $true Write-LogMessage -message 'Reloaded authentication data from KeyVault' -Sev 'debug' -API 'CIPP Authentication' return $true diff --git a/Modules/CIPPCore/Public/Get-CIPPAzDatatableEntity.ps1 b/Modules/CIPPCore/Public/Get-CIPPAzDatatableEntity.ps1 index 27c4002fb814..cd1fbce70771 100644 --- a/Modules/CIPPCore/Public/Get-CIPPAzDatatableEntity.ps1 +++ b/Modules/CIPPCore/Public/Get-CIPPAzDatatableEntity.ps1 @@ -12,31 +12,43 @@ function Get-CIPPAzDataTableEntity { $Results = Get-AzDataTableEntity @PSBoundParameters $mergedResults = @{} + $rootEntities = @{} # Keyed by "$PartitionKey|$RowKey" - # First pass: Collect all parts and complete entities foreach ($entity in $Results) { - if ($entity.OriginalEntityId) { - $entityId = $entity.OriginalEntityId - $partitionKey = $entity.PartitionKey - if (-not $mergedResults.ContainsKey($partitionKey)) { - $mergedResults[$partitionKey] = @{} - } - if (-not $mergedResults[$partitionKey].ContainsKey($entityId)) { - $mergedResults[$partitionKey][$entityId] = @{ - Parts = [System.Collections.Generic.List[object]]::new() - } - } - $mergedResults[$partitionKey][$entityId]['Parts'].Add($entity) - } else { - $partitionKey = $entity.PartitionKey - if (-not $mergedResults.ContainsKey($partitionKey)) { - $mergedResults[$partitionKey] = @{} - } - $mergedResults[$partitionKey][$entity.RowKey] = @{ + $partitionKey = $entity.PartitionKey + $rowKey = $entity.RowKey + $hasOriginalId = $entity.PSObject.Properties.Match('OriginalEntityId') -and $entity.OriginalEntityId + + if (-not $mergedResults.ContainsKey($partitionKey)) { + $mergedResults[$partitionKey] = @{} + } + + if (-not $hasOriginalId) { + # It's a standalone root row + $rootEntities["$partitionKey|$rowKey"] = $true + $mergedResults[$partitionKey][$rowKey] = @{ Entity = $entity Parts = [System.Collections.Generic.List[object]]::new() } + continue + } + + # It's a part of something else + $entityId = $entity.OriginalEntityId + + # Check if this entity's target has a "real" base + if ($rootEntities.ContainsKey("$partitionKey|$entityId")) { + # Root row exists → skip merging this part + continue + } + + # Merge it as a part + if (-not $mergedResults[$partitionKey].ContainsKey($entityId)) { + $mergedResults[$partitionKey][$entityId] = @{ + Parts = [System.Collections.Generic.List[object]]::new() + } } + $mergedResults[$partitionKey][$entityId]['Parts'].Add($entity) } $finalResults = [System.Collections.Generic.List[object]]::new() diff --git a/Modules/CIPPCore/Public/Get-CIPPGeoIPLocation.ps1 b/Modules/CIPPCore/Public/Get-CIPPGeoIPLocation.ps1 index 1ee4efcd43df..92595a0f580d 100644 --- a/Modules/CIPPCore/Public/Get-CIPPGeoIPLocation.ps1 +++ b/Modules/CIPPCore/Public/Get-CIPPGeoIPLocation.ps1 @@ -6,7 +6,7 @@ function Get-CIPPGeoIPLocation { $CacheGeoIPTable = Get-CippTable -tablename 'cachegeoip' $30DaysAgo = (Get-Date).AddDays(-30).ToString('yyyy-MM-ddTHH:mm:ssZ') - $Filter = "RowKey eq '$IP' and Timestamp ge datetime'$30DaysAgo'" + $Filter = "PartitionKey eq 'IP' and RowKey eq '$IP' and Timestamp ge datetime'$30DaysAgo'" $GeoIP = Get-CippAzDataTableEntity @CacheGeoIPTable -Filter $Filter if ($GeoIP) { return ($GeoIP.Data | ConvertFrom-Json) diff --git a/Modules/CIPPCore/Public/Get-CIPPSchemaExtensions.ps1 b/Modules/CIPPCore/Public/Get-CIPPSchemaExtensions.ps1 index f4392cad0b53..cfc5ed0d9998 100644 --- a/Modules/CIPPCore/Public/Get-CIPPSchemaExtensions.ps1 +++ b/Modules/CIPPCore/Public/Get-CIPPSchemaExtensions.ps1 @@ -34,7 +34,7 @@ function Get-CIPPSchemaExtensions { $SchemaExtensions = Get-CIPPAzDataTableEntity @CustomDataTable -Filter "PartitionKey eq 'SchemaExtension'" } - $Schemas = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/schemaExtensions?`$filter=owner eq '$($ENV:ApplicationID)'" -NoAuthCheck $true -AsApp $true | Where-Object { $_.status -ne 'Deprecated' } + $Schemas = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/schemaExtensions?`$filter=owner eq '$($env:ApplicationID)'" -NoAuthCheck $true -AsApp $true | Where-Object { $_.status -ne 'Deprecated' } foreach ($SchemaExtension in $SchemaExtensions) { $SchemaFound = $false diff --git a/Modules/CIPPCore/Public/Get-CIPPTextReplacement.ps1 b/Modules/CIPPCore/Public/Get-CIPPTextReplacement.ps1 index ba744b23b870..28ad7d8a7343 100644 --- a/Modules/CIPPCore/Public/Get-CIPPTextReplacement.ps1 +++ b/Modules/CIPPCore/Public/Get-CIPPTextReplacement.ps1 @@ -19,6 +19,25 @@ function Get-CIPPTextReplacement { return $Text } + $ReservedVariables = @( + '%serial%', + '%systemroot%', + '%systemdrive%', + '%temp%', + '%tenantid%', + '%tenantfilter%', + '%tenantname%', + '%partnertenantid%', + '%samappid%', + '%userprofile%', + '%username%', + '%userdomain%', + '%windir%', + '%programfiles%', + '%programfiles(x86)%', + '%programdata%' + ) + $Tenant = Get-Tenants -TenantFilter $TenantFilter $CustomerId = $Tenant.customerId @@ -44,7 +63,9 @@ function Get-CIPPTextReplacement { # Replace custom variables foreach ($Replace in $Vars.GetEnumerator()) { $String = '%{0}%' -f $Replace.Key - $Text = $Text -replace $String, $Replace.Value + if ($string -notin $ReservedVariables) { + $Text = $Text -replace $String, $Replace.Value + } } #default replacements for all tenants: %tenantid% becomes $tenant.customerId, %tenantfilter% becomes $tenant.defaultDomainName, %tenantname% becomes $tenant.displayName $Text = $Text -replace '%tenantid%', $Tenant.customerId @@ -52,7 +73,7 @@ function Get-CIPPTextReplacement { $Text = $Text -replace '%tenantname%', $Tenant.displayName # Partner specific replacements - $Text = $Text -replace '%partnertenantid%', $ENV:TenantID - $Text = $Text -replace '%samappid%', $ENV:ApplicationID + $Text = $Text -replace '%partnertenantid%', $env:TenantID + $Text = $Text -replace '%samappid%', $env:ApplicationID return $Text } diff --git a/Modules/CIPPCore/Public/Get-TenantIdFromSubscriptionId.ps1 b/Modules/CIPPCore/Public/Get-TenantIdFromSubscriptionId.ps1 new file mode 100644 index 000000000000..5c7547fc8b2e --- /dev/null +++ b/Modules/CIPPCore/Public/Get-TenantIdFromSubscriptionId.ps1 @@ -0,0 +1,26 @@ +function Get-TenantIdFromSubscriptionId { + param ( + [Parameter(Mandatory = $true)] + [string]$SubscriptionId + ) + + # Full credit goes to Jos Lieben + # https://www.lieben.nu/liebensraum/2020/08/get-tenant-id-using-azure-subscription-id/ + + try { + Invoke-WebRequest -UseBasicParsing -Uri "https://management.azure.com/subscriptions/$($SubscriptionId)`?api-version=2015-01-01" -ErrorAction Stop + } catch { + # The error response contains the WWW-Authenticate header with the tenant ID + $response = $_.Exception.Response + } + + # Extract tenant ID from WWW-Authenticate header + $authHeader = $response.Headers.GetValues("WWW-Authenticate")[0] + + # Use regex to extract the tenant ID + if ($authHeader -match "login\.windows\.net\/([0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12})") { + return $matches[1] + } + + return $null +} diff --git a/Modules/CIPPCore/Public/GraphHelper/Get-ClassicAPIToken.ps1 b/Modules/CIPPCore/Public/GraphHelper/Get-ClassicAPIToken.ps1 index 5a10c27f1e38..23bd67941e56 100644 --- a/Modules/CIPPCore/Public/GraphHelper/Get-ClassicAPIToken.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/Get-ClassicAPIToken.ps1 @@ -11,7 +11,7 @@ function Get-ClassicAPIToken($tenantID, $Resource) { #Write-Host 'Using classic' $uri = "https://login.microsoftonline.com/$($TenantID)/oauth2/token" $Body = @{ - client_id = $ENV:ApplicationID + client_id = $env:ApplicationID client_secret = $env:ApplicationSecret resource = $Resource refresh_token = $env:RefreshToken diff --git a/Modules/CIPPCore/Public/GraphHelper/New-ExoBulkRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-ExoBulkRequest.ps1 index b7c16875692b..38275011282b 100644 --- a/Modules/CIPPCore/Public/GraphHelper/New-ExoBulkRequest.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/New-ExoBulkRequest.ps1 @@ -84,6 +84,7 @@ function New-ExoBulkRequest { $IdToCmdletName[$RequestId] = $cmd.CmdletInput.CmdletName } $BatchBodyJson = ConvertTo-Json -InputObject $BatchBodyObj -Depth 10 + $BatchBodyJson = Get-CIPPTextReplacement -TenantFilter $tenantid -Text $BatchBodyJson $Results = Invoke-RestMethod $BatchURL -ResponseHeadersVariable responseHeaders -Method POST -Body $BatchBodyJson -Headers $Headers -ContentType 'application/json; charset=utf-8' foreach ($Response in $Results.responses) { $ReturnedData.Add($Response) diff --git a/Modules/CIPPCore/Public/GraphHelper/New-ExoRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-ExoRequest.ps1 index 6635307ead0e..3f42b22ae2e1 100644 --- a/Modules/CIPPCore/Public/GraphHelper/New-ExoRequest.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/New-ExoRequest.ps1 @@ -54,6 +54,7 @@ function New-ExoRequest { Parameters = $Params } } + $ExoBody = Get-CIPPTextReplacement -TenantFilter $tenantid -Text $ExoBody $Tenant = Get-Tenants -IncludeErrors | Where-Object { $_.defaultDomainName -eq $tenantid -or $_.customerId -eq $tenantid } if (-not $Tenant -and $NoAuthCheck -eq $true) { diff --git a/Modules/CIPPCore/Public/GraphHelper/New-GraphPOSTRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-GraphPOSTRequest.ps1 index 753a47922b66..73fa5b11845c 100644 --- a/Modules/CIPPCore/Public/GraphHelper/New-GraphPOSTRequest.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/New-GraphPOSTRequest.ps1 @@ -20,6 +20,7 @@ function New-GraphPOSTRequest ($uri, $tenantid, $body, $type, $scope, $AsApp, $N $contentType = 'application/json; charset=utf-8' } try { + $body = Get-CIPPTextReplacement -TenantFilter $tenantid -Text $body $ReturnedData = (Invoke-RestMethod -Uri $($uri) -Method $TYPE -Body $body -Headers $headers -ContentType $contentType -SkipHttpErrorCheck:$IgnoreErrors -ResponseHeadersVariable responseHeaders) } catch { $Message = if ($_.ErrorDetails.Message) { @@ -37,4 +38,4 @@ function New-GraphPOSTRequest ($uri, $tenantid, $body, $type, $scope, $AsApp, $N } else { Write-Error 'Not allowed. You cannot manage your own tenant or tenants not under your scope' } -} \ No newline at end of file +} diff --git a/Modules/CIPPCore/Public/GraphHelper/Remove-CIPPCache.ps1 b/Modules/CIPPCore/Public/GraphHelper/Remove-CIPPCache.ps1 index 9dca6bdc7b1f..acb67becb66e 100644 --- a/Modules/CIPPCore/Public/GraphHelper/Remove-CIPPCache.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/Remove-CIPPCache.ps1 @@ -39,7 +39,7 @@ function Remove-CIPPCache { Update-AzDataTableEntity -Force @DomainsTable -Entity $ClearDomainAnalyserRows } - $ENV:SetFromProfile = $null + $env:SetFromProfile = $null $Script:SkipListCache = $Null $Script:SkipListCacheEmpty = $Null $Script:IncludedTenantsCache = $Null diff --git a/Modules/CIPPCore/Public/Invoke-RemoveQueuedApp.ps1 b/Modules/CIPPCore/Public/Invoke-RemoveQueuedApp.ps1 index 4cbe632f33f3..6c80a2c62572 100644 --- a/Modules/CIPPCore/Public/Invoke-RemoveQueuedApp.ps1 +++ b/Modules/CIPPCore/Public/Invoke-RemoveQueuedApp.ps1 @@ -11,7 +11,8 @@ Function Invoke-RemoveQueuedApp { 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' $ID = $request.body.ID try { diff --git a/Modules/CIPPCore/Public/New-CIPPAlertTemplate.ps1 b/Modules/CIPPCore/Public/New-CIPPAlertTemplate.ps1 index abd0b6b3604b..bf93a9098812 100644 --- a/Modules/CIPPCore/Public/New-CIPPAlertTemplate.ps1 +++ b/Modules/CIPPCore/Public/New-CIPPAlertTemplate.ps1 @@ -12,7 +12,7 @@ function New-CIPPAlertTemplate { $AuditLogLink ) $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 $data.applicationId - $HTMLTemplate = Get-Content 'TemplateEmail.HTML' -Raw | Out-String + $HTMLTemplate = Get-Content 'TemplateEmail.html' -Raw | Out-String $Title = '' $IntroText = '' $ButtonUrl = '' @@ -31,6 +31,17 @@ function New-CIPPAlertTemplate { if ($InputObject -eq 'sherwebmig') { $DataHTML = ($Data | ConvertTo-Html | Out-String).Replace('', '
') $IntroText = "

The following licenses have not yet been found at Sherweb, and are expiring within 7 days:

$dataHTML" + if ($data.SherwebMig -like '*buy*') { + $introText = "

The following licenses have not yet been found at Sherweb, and are expiring within 7 days. We have started the process to automatically buy these licenses:

$dataHTML" + } + } + if ($InputObject -eq 'sherwebmigfailcancel') { + $DataHTML = ($Data | ConvertTo-Html | Out-String).Replace('
', '
') + $IntroText = "

The following licenses have not been cancelled due to an API error at the old provider:

$dataHTML" + } + if ($InputObject -eq 'sherwebmigBuyFail') { + $DataHTML = ($Data | ConvertTo-Html | Out-String).Replace('
', '
') + $IntroText = "

The following licenses have not been bought as we could not find a correctly matching license. Please login and buy the license:

$dataHTML" } if ($InputObject -eq 'table') { #data can be a array of strings or a string, if it is, we need to convert it to an object so it shows up nicely, that object will have one header: message. diff --git a/Modules/CIPPCore/Public/New-CIPPApplicationCopy.ps1 b/Modules/CIPPCore/Public/New-CIPPApplicationCopy.ps1 index bdc198c10f8a..4c7a9febeceb 100644 --- a/Modules/CIPPCore/Public/New-CIPPApplicationCopy.ps1 +++ b/Modules/CIPPCore/Public/New-CIPPApplicationCopy.ps1 @@ -15,15 +15,15 @@ function New-CIPPApplicationCopy { try { try { - $ExistingApp = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/applications(appId='$($app)')" -tenantid $ENV:TenantID -NoAuthCheck $true -AsApp $true + $ExistingApp = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/applications(appId='$($app)')" -tenantid $env:TenantID -NoAuthCheck $true -AsApp $true $Type = 'Application' } catch { - $ExistingApp = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals(appId='$($app)')/oauth2PermissionGrants" -tenantid $ENV:TenantID -NoAuthCheck $true -AsApp $true - $ExistingAppRoleAssignments = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals(appId='$($app)')/appRoleAssignments" -tenantid $ENV:TenantID -NoAuthCheck $true -AsApp $true + $ExistingApp = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals(appId='$($app)')/oauth2PermissionGrants" -tenantid $env:TenantID -NoAuthCheck $true -AsApp $true + $ExistingAppRoleAssignments = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals(appId='$($app)')/appRoleAssignments" -tenantid $env:TenantID -NoAuthCheck $true -AsApp $true $Type = 'ServicePrincipal' } - if (!$ExistingApp) { - Write-LogMessage -message "Failed to add $App to tenant. This app does not exist." -tenant $tenant -API 'Application Copy' -sev error + if (!$ExistingApp -and !$ExistingAppRoleAssignments) { + Write-LogMessage -message "Failed to add $App to tenant. This app does not exist or does not have any consented permissions." -tenant $tenant -API 'Application Copy' -sev error continue } if ($Type -eq 'Application') { diff --git a/Modules/CIPPCore/Public/New-CIPPCAPolicy.ps1 b/Modules/CIPPCore/Public/New-CIPPCAPolicy.ps1 index b57859c9b197..75c4fb04cfa4 100644 --- a/Modules/CIPPCore/Public/New-CIPPCAPolicy.ps1 +++ b/Modules/CIPPCore/Public/New-CIPPCAPolicy.ps1 @@ -235,6 +235,10 @@ function New-CIPPCAPolicy { } } else { Write-Information 'Creating' + if ($JSONobj.GrantControls.authenticationStrength.policyType -or $JSONObj.$jsonobj.LocationInfo) { + #quick fix for if the policy isn't available + Start-Sleep 1 + } $null = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/policies' -tenantid $tenantfilter -type POST -body $RawJSON -asApp $true Write-LogMessage -Headers $User -API $APINAME -tenant $($Tenant) -message "Added Conditional Access Policy $($JSONObj.Displayname)" -Sev 'Info' return "Created policy $displayname for $tenantfilter" diff --git a/Modules/CIPPCore/Public/New-CIPPTemplateRun.ps1 b/Modules/CIPPCore/Public/New-CIPPTemplateRun.ps1 index 1c10bda343be..da61eb588ca9 100644 --- a/Modules/CIPPCore/Public/New-CIPPTemplateRun.ps1 +++ b/Modules/CIPPCore/Public/New-CIPPTemplateRun.ps1 @@ -13,6 +13,13 @@ function New-CIPPTemplateRun { $data } | Sort-Object -Property displayName + function Get-SanitizedFilename { + param ( + [string]$filename + ) + $filename = $filename -replace '\s', '_' -replace '[^\w\d_]', '' + return $filename + } $Tasks = foreach ($key in $TemplateSettings.Keys) { if ($TemplateSettings[$key] -eq $true) { @@ -20,40 +27,54 @@ function New-CIPPTemplateRun { } } if ($TemplateSettings.templateRepo) { - Write-Host 'Grabbing data from required community repo' - $Files = (Get-GitHubFileTree -FullName $TemplateSettings.templateRepo.value -Branch $TemplateSettings.templateRepoBranch.value).tree | Where-Object { $_.path -match '.json$' -and $_.path -notmatch 'NativeImport' } | Select-Object *, @{n = 'html_url'; e = { "https://github.com/$($SplatParams.FullName)/tree/$($SplatParams.Branch)/$($_.path)" } }, @{n = 'name'; e = { ($_.path -split '/')[ -1 ] -replace '\.json$', '' } } - #if there is a migration table file, file the file. Store the file contents in $migrationtable - $MigrationTable = $Files | Where-Object { $_.name -eq 'MigrationTable' } | Select-Object -Last 1 - if ($MigrationTable) { - $MigrationTable = (Get-GitHubFileContents -FullName $TemplateSettings.templateRepo.value -Branch $TemplateSettings.templateRepoBranch.value -Path $MigrationTable.path).content | ConvertFrom-Json - } - foreach ($File in $Files) { - if ($File.name -eq 'MigrationTable' -or $file.name -eq 'ALLOWED COUNTRIES') { continue } - $ExistingTemplate = $ExistingTemplates | Where-Object { $_.displayName -eq $File.name } | Select-Object -First 1 - $Template = (Get-GitHubFileContents -FullName $TemplateSettings.templateRepo.value -Branch $TemplateSettings.templateRepoBranch.value -Path $File.path).content | ConvertFrom-Json - if ($ExistingTemplate) { + Write-Information 'Grabbing data from community repo' + try { + $Files = (Get-GitHubFileTree -FullName $TemplateSettings.templateRepo.value -Branch $TemplateSettings.templateRepoBranch.value).tree | Where-Object { $_.path -match '.json$' -and $_.path -notmatch 'NativeImport' } | Select-Object *, @{n = 'html_url'; e = { "https://github.com/$($SplatParams.FullName)/tree/$($SplatParams.Branch)/$($_.path)" } }, @{n = 'name'; e = { ($_.path -split '/')[ -1 ] -replace '\.json$', '' } } + #if there is a migration table file, file the file. Store the file contents in $migrationtable + $MigrationTable = $Files | Where-Object { $_.name -eq 'MigrationTable' } | Select-Object -Last 1 + if ($MigrationTable) { + $MigrationTable = (Get-GitHubFileContents -FullName $TemplateSettings.templateRepo.value -Branch $TemplateSettings.templateRepoBranch.value -Path $MigrationTable.path).content | ConvertFrom-Json + } + foreach ($File in $Files) { + if ($File.name -eq 'MigrationTable' -or $file.name -eq 'ALLOWED COUNTRIES') { continue } + $ExistingTemplate = $ExistingTemplates | Where-Object { (![string]::IsNullOrEmpty($_.displayName) -and (Get-SanitizedFilename -filename $_.displayName) -eq $File.name) -or (![string]::IsNullOrEmpty($_.templateName) -and (Get-SanitizedFilename -filename $_.templateName) -eq $File.name ) } | Select-Object -First 1 + $UpdateNeeded = $false - if ($ExistingTemplate.sha -ne $File.sha -or !$ExistingTemplate.sha) { + if ($ExistingTemplate -and $ExistingTemplate.SHA -ne $File.sha) { + $Name = $ExistingTemplate.displayName ?? $ExistingTemplate.templateName + Write-Information "Existing template $($Name) found, but SHA is different. Updating template." $UpdateNeeded = $true + "Template $($Name) needs to be updated as the SHA is different" + } else { + Write-Information "Existing template $($File.name) found, but SHA is the same. No update needed." + "Template $($File.name) found, but SHA is the same. No update needed." } - if ($UpdateNeeded) { - Write-Host "Template $($File.name) needs to be updated as the SHA is different" + + if (!$ExistingTemplate -or $UpdateNeeded) { + $Template = (Get-GitHubFileContents -FullName $TemplateSettings.templateRepo.value -Branch $TemplateSettings.templateRepoBranch.value -Path $File.path).content | ConvertFrom-Json Import-CommunityTemplate -Template $Template -SHA $File.sha -MigrationTable $MigrationTable + if ($UpdateNeeded) { + Write-Information "Template $($File.name) needs to be updated as the SHA is different" + "Template $($File.name) updated" + } else { + Write-Information "Template $($File.name) needs to be created" + "Template $($File.name) created" + } } - } else { - Write-Host "Template $($File.name) needs to be created" - Import-CommunityTemplate -Template $Template -SHA $File.sha -MigrationTable $MigrationTable - } + } catch { + $Message = "Failed to get data from community repo $($TemplateSettings.templateRepo.value). Error: $($_.Exception.Message)" + Write-LogMessage -API 'Community Repo' -tenant $TenantFilter -message $Message -sev Error + return "Failed to get data from community repo $($TemplateSettings.templateRepo.value). Error: $($_.Exception.Message)" } } else { foreach ($Task in $Tasks) { - Write-Host "Working on task $Task" + Write-Information "Working on task $Task" switch ($Task) { 'ca' { - Write-Host "Template Conditional Access Policies for $TenantFilter" + Write-Information "Template Conditional Access Policies for $TenantFilter" $Policies = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/conditionalAccess/policies?$top=999' -tenantid $TenantFilter - Write-Host 'Creating templates for found Conditional Access Policies' + Write-Information 'Creating templates for found Conditional Access Policies' foreach ($policy in $policies) { try { $Template = New-CIPPCATemplate -TenantFilter $TenantFilter -JSON $policy @@ -84,7 +105,7 @@ function New-CIPPTemplateRun { } } 'intuneconfig' { - Write-Host "Backup Intune Configuration Policies for $TenantFilter" + Write-Information "Backup Intune Configuration Policies for $TenantFilter" $GraphURLS = @("https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations?`$select=id,displayName,lastModifiedDateTime,roleScopeTagIds,microsoft.graph.unsupportedDeviceConfiguration/originalEntityTypeName&`$expand=assignments&top=1000" 'https://graph.microsoft.com/beta/deviceManagement/windowsDriverUpdateProfiles' "https://graph.microsoft.com/beta/deviceManagement/groupPolicyConfigurations?`$expand=assignments&top=999" @@ -141,12 +162,12 @@ function New-CIPPTemplateRun { } } } catch { - Write-Host "Failed to backup $url" + Write-Information "Failed to backup $url" } } } 'intunecompliance' { - Write-Host "Backup Intune Compliance Policies for $TenantFilter" + Write-Information "Backup Intune Compliance Policies for $TenantFilter" New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/deviceCompliancePolicies?$top=999' -tenantid $TenantFilter | ForEach-Object { $Template = New-CIPPIntuneTemplate -TenantFilter $TenantFilter -URLName 'deviceCompliancePolicies' -ID $_.ID $ExistingPolicy = $ExistingTemplates | Where-Object { $_.displayName -eq $Template.DisplayName } | Select-Object -First 1 @@ -187,7 +208,7 @@ function New-CIPPTemplateRun { } 'intuneprotection' { - Write-Host "Backup Intune Protection Policies for $TenantFilter" + Write-Information "Backup Intune Protection Policies for $TenantFilter" New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/deviceAppManagement/managedAppPolicies?$top=999' -tenantid $TenantFilter | ForEach-Object { $Template = New-CIPPIntuneTemplate -TenantFilter $TenantFilter -URLName 'managedAppPolicies' -ID $_.ID $ExistingPolicy = $ExistingTemplates | Where-Object { $_.displayName -eq $Template.DisplayName } | Select-Object -First 1 diff --git a/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 b/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 index b7fcec73a316..933f6fbdb99e 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 @@ -11,7 +11,7 @@ function Remove-CIPPGroups { if (-not $userid) { $userid = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($Username)" -tenantid $Tenantfilter).id } - $AllGroups = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/groups/?`$select=displayName,mailEnabled,id,groupTypes" -tenantid $tenantFilter) + $AllGroups = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/groups/?`$select=displayName,mailEnabled,id,groupTypes,assignedLicenses&`$top=999" -tenantid $tenantFilter) $Returnval = (New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($userid)/GetMemberGroups" -tenantid $tenantFilter -type POST -body '{"securityEnabledOnly": false}').value | ForEach-Object -Parallel { Import-Module '.\Modules\AzBobbyTables' @@ -22,18 +22,23 @@ function Remove-CIPPGroups { $Groupname = ($using:AllGroups | Where-Object -Property id -EQ $group).displayName $IsMailEnabled = ($using:AllGroups | Where-Object -Property id -EQ $group).mailEnabled $IsM365Group = $null -ne ($using:AllGroups | Where-Object { $_.id -eq $group -and $_.groupTypes -contains 'Unified' }) + $IsLicensed = ($using:AllGroups | Where-Object -Property id -EQ $group).assignedLicenses.Count -gt 0 - if ($IsM365Group) { - $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$_/members/$($using:userid)/`$ref" -tenantid $using:tenantFilter -type DELETE -body '' -Verbose - } elseif (-not $IsMailEnabled) { - $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$_/members/$($using:userid)/`$ref" -tenantid $using:tenantFilter -type DELETE -body '' -Verbose - } elseif ($IsMailEnabled) { - $Params = @{ Identity = $Groupname; Member = $using:userid ; BypassSecurityGroupManagerCheck = $true } - New-ExoRequest -tenantid $using:tenantFilter -cmdlet 'Remove-DistributionGroupMember' -cmdParams $params -UseSystemMailbox $true - } + if ($IsLicensed) { + "Could not remove $($using:Username) from $Groupname. This is because the group has licenses assigned to it." + } else { + if ($IsM365Group) { + $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$_/members/$($using:userid)/`$ref" -tenantid $using:tenantFilter -type DELETE -body '' -Verbose + } elseif (-not $IsMailEnabled) { + $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$_/members/$($using:userid)/`$ref" -tenantid $using:tenantFilter -type DELETE -body '' -Verbose + } elseif ($IsMailEnabled) { + $Params = @{ Identity = $Groupname; Member = $using:userid ; BypassSecurityGroupManagerCheck = $true } + New-ExoRequest -tenantid $using:tenantFilter -cmdlet 'Remove-DistributionGroupMember' -cmdParams $params -UseSystemMailbox $true + } - Write-LogMessage -headers $using:Headers -API $($using:APIName) -message "Removed $($using:Username) from $groupname" -Sev 'Info' -tenant $using:TenantFilter - "Successfully removed $($using:Username) from group $Groupname" + Write-LogMessage -headers $using:Headers -API $($using:APIName) -message "Removed $($using:Username) from $groupname" -Sev 'Info' -tenant $using:TenantFilter + "Successfully removed $($using:Username) from group $Groupname" + } } catch { $ErrorMessage = Get-CippException -Exception $_ Write-LogMessage -headers $using:Headers -API $($using:APIName) -message "Could not remove $($using:Username) from group $groupname : $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $using:TenantFilter -LogData $ErrorMessage diff --git a/Modules/CIPPCore/Public/Remove-CIPPLicense.ps1 b/Modules/CIPPCore/Public/Remove-CIPPLicense.ps1 index 30c8e6c10abc..b2d8d447e9d1 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPLicense.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPLicense.ps1 @@ -35,6 +35,36 @@ function Remove-CIPPLicense { try { $ConvertTable = Import-Csv ConversionTable.csv $User = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($userid)" -tenantid $tenantFilter + $GroupMemberships = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($userid)/memberOf/microsoft.graph.group?`$select=id,displayName,assignedLicenses" -tenantid $tenantFilter + $LicenseGroups = $GroupMemberships | Where-Object { ($_.assignedLicenses | Measure-Object).Count -gt 0 } + + if ($LicenseGroups) { + # remove user from groups with licenses, these can only be graph groups + $RemoveRequests = foreach ($LicenseGroup in $LicenseGroups) { + @{ + id = $LicenseGroup.id + method = 'DELETE' + url = "groups/$($LicenseGroup.id)/members/$($User.id)/`$ref" + } + } + + Write-Information 'Removing user from groups with licenses' + $RemoveResults = New-GraphBulkRequest -tenantid $tenantFilter -requests @($RemoveRequests) + Write-Information ($RemoveResults | ConvertTo-Json -Depth 5) + $RemoveResults | ForEach-Object { + $Group = $GroupMemberships | Where-Object { $_.id -eq $_.id } + $GroupName = $Group | Select-Object -ExpandProperty displayName + + if ($_.status -eq 204) { + Write-LogMessage -headers $Headers -API $APIName -message "Removed $($User.displayName) from license group $GroupName" -Sev 'Info' -tenant $TenantFilter + "Removed $($User.displayName) from license group $GroupName" + } else { + Write-LogMessage -headers $Headers -API $APIName -message "Failed to remove $($User.displayName) from license group $GroupName. This is likely because its a Dynamic Group or synced with active directory." -Sev 'Error' -tenant $TenantFilter + "Failed to remove $($User.displayName) from license group $GroupName. This is likely because its a Dynamic Group or synced with active directory." + } + } + } + if (!$username) { $username = $User.userPrincipalName } $CurrentLicenses = $User.assignedlicenses.skuid $ConvertedLicense = $(($ConvertTable | Where-Object { $_.guid -in $CurrentLicenses }).'Product_Display_Name' | Sort-Object -Unique) -join ', ' diff --git a/Modules/CIPPCore/Public/Remove-CIPPMailboxRule.ps1 b/Modules/CIPPCore/Public/Remove-CIPPMailboxRule.ps1 index fbc5cd2d436e..aeb62aad3446 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPMailboxRule.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPMailboxRule.ps1 @@ -1,8 +1,8 @@ function Remove-CIPPMailboxRule { [CmdletBinding()] param ( - $userid, - $username, + $UserId, + $Username, $TenantFilter, $APIName = 'Mailbox Rules Removal', $Headers, @@ -14,35 +14,34 @@ function Remove-CIPPMailboxRule { if ($RemoveAllRules.IsPresent -eq $true) { # Delete all rules try { - Write-Host "Checking rules for $username" - $rules = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-InboxRule' -cmdParams @{Mailbox = $username; IncludeHidden = $true } | Where-Object { $_.Name -ne 'Junk E-Mail Rule' -and $_.Name -notlike 'Microsoft.Exchange.OOF.*' } - Write-Host "$($rules.count) rules found" - if ($null -eq $rules) { - Write-LogMessage -headers $Headers -API $APIName -message "No Rules for $($username) to delete" -Sev 'Info' -tenant $TenantFilter - return "No rules for $($username) to delete" + Write-Host "Checking rules for $Username" + $Rules = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-InboxRule' -cmdParams @{Mailbox = $Username; IncludeHidden = $true } | Where-Object { $_.Name -ne 'Junk E-Mail Rule' -and $_.Name -notlike 'Microsoft.Exchange.OOF.*' } + Write-Host "$($Rules.count) rules found" + if ($null -eq $Rules) { + Write-LogMessage -headers $Headers -API $APIName -message "No Rules for $($Username) to delete" -Sev 'Info' -tenant $TenantFilter + return "No rules for $($Username) to delete" } else { - ForEach ($rule in $rules) { - $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Remove-InboxRule' -Anchor $username -cmdParams @{Identity = $rule.Identity } + ForEach ($rule in $Rules) { + $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)" + Write-LogMessage -headers $Headers -API $APIName -message "Deleted rules for $($Username)" -Sev 'Info' -tenant $TenantFilter + return "Deleted rules for $($Username)" } } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers -API $APIName -message "Could not delete rules for $($username): $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - return "Could not delete rules for $($username). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message "Could not delete rules for $($Username): $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + return "Could not delete rules for $($Username). Error: $($ErrorMessage.NormalizedError)" } } else { # Only delete 1 rule try { - $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Remove-InboxRule' -Anchor $username -cmdParams @{Identity = $RuleId } - Write-LogMessage -headers $Headers -API $APIName -message "Deleted mailbox rule $($RuleName) for $($username)" -Sev 'Info' -tenant $TenantFilter - return "Deleted mailbox rule $($RuleName) for $($username)" + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Remove-InboxRule' -Anchor $Username -cmdParams @{Identity = $RuleId } + Write-LogMessage -headers $Headers -API $APIName -message "Deleted mailbox rule $($RuleName) for $($Username)" -Sev 'Info' -tenant $TenantFilter + return "Deleted mailbox rule $($RuleName) for $($Username)" } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers -API $APIName -message "Could not delete rule for $($username): $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - return "Could not delete rule for $($username). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message "Could not delete rule for $($Username): $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + return "Could not delete rule for $($Username). Error: $($ErrorMessage.NormalizedError)" } } } - diff --git a/Modules/CIPPCore/Public/Set-CIPPCPVConsent.ps1 b/Modules/CIPPCore/Public/Set-CIPPCPVConsent.ps1 index 339e4e278a5a..d8b09f367017 100644 --- a/Modules/CIPPCore/Public/Set-CIPPCPVConsent.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPCPVConsent.ps1 @@ -20,8 +20,8 @@ function Set-CIPPCPVConsent { if ($ResetSP) { try { - if ($PSCmdlet.ShouldProcess($ENV:ApplicationID, "Delete Service Principal from $TenantName")) { - $null = New-GraphPostRequest -Type DELETE -noauthcheck $true -uri "https://api.partnercenter.microsoft.com/v1/customers/$($TenantFilter)/applicationconsents/$($ENV:ApplicationID)" -scope 'https://api.partnercenter.microsoft.com/.default' -tenantid $env:TenantID + if ($PSCmdlet.ShouldProcess($env:ApplicationID, "Delete Service Principal from $TenantName")) { + $null = New-GraphPostRequest -Type DELETE -noauthcheck $true -uri "https://api.partnercenter.microsoft.com/v1/customers/$($TenantFilter)/applicationconsents/$($env:ApplicationID)" -scope 'https://api.partnercenter.microsoft.com/.default' -tenantid $env:TenantID } $Results.add("Deleted Service Principal from $TenantName") } catch { @@ -32,7 +32,7 @@ function Set-CIPPCPVConsent { try { $AppBody = @{ - ApplicationId = $($ENV:ApplicationID) + ApplicationId = $($env:ApplicationID) ApplicationGrants = @( @{ EnterpriseApplicationId = '00000003-0000-0000-c000-000000000000' @@ -45,13 +45,13 @@ function Set-CIPPCPVConsent { ) } | ConvertTo-Json - if ($PSCmdlet.ShouldProcess($ENV:ApplicationID, "Add Service Principal to $TenantName")) { + if ($PSCmdlet.ShouldProcess($env:ApplicationID, "Add Service Principal to $TenantName")) { $null = New-GraphpostRequest -body $AppBody -Type POST -noauthcheck $true -uri "https://api.partnercenter.microsoft.com/v1/customers/$($TenantFilter)/applicationconsents" -scope 'https://api.partnercenter.microsoft.com/.default' -tenantid $env:TenantID $Table = Get-CIPPTable -TableName cpvtenants $unixtime = [int64](([datetime]::UtcNow) - (Get-Date '1/1/1970')).TotalSeconds $GraphRequest = @{ LastApply = "$unixtime" - applicationId = "$($ENV:ApplicationID)" + applicationId = "$($env:ApplicationID)" Tenant = "$($tenantfilter)" PartitionKey = 'Tenant' RowKey = "$($tenantfilter)" @@ -67,7 +67,7 @@ function Set-CIPPCPVConsent { $unixtime = [int64](([datetime]::UtcNow) - (Get-Date '1/1/1970')).TotalSeconds $GraphRequest = @{ LastApply = "$unixtime" - applicationId = "$($ENV:ApplicationID)" + applicationId = "$($env:ApplicationID)" Tenant = "$($tenantfilter)" PartitionKey = 'Tenant' RowKey = "$($tenantfilter)" diff --git a/Modules/CIPPCore/Public/Set-CIPPDefaultAPDeploymentProfile.ps1 b/Modules/CIPPCore/Public/Set-CIPPDefaultAPDeploymentProfile.ps1 index f257a9189a6c..159fe55e8326 100644 --- a/Modules/CIPPCore/Public/Set-CIPPDefaultAPDeploymentProfile.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPDefaultAPDeploymentProfile.ps1 @@ -33,13 +33,13 @@ function Set-CIPPDefaultAPDeploymentProfile { 'extractHardwareHash' = $([bool]($CollectHash)) 'roleScopeTagIds' = @() 'hybridAzureADJoinSkipConnectivityCheck' = $false - 'outOfBoxExperienceSettings' = @{ + 'outOfBoxExperienceSetting' = @{ 'deviceUsageType' = "$DeploymentMode" - 'hideEscapeLink' = $([bool]($hideChangeAccount)) - 'hidePrivacySettings' = $([bool]($hidePrivacy)) - 'hideEULA' = $([bool]($hideTerms)) + 'escapeLinkHidden' = $([bool]($hideChangeAccount)) + 'privacySettingsHidden' = $([bool]($hidePrivacy)) + 'eulaHidden' = $([bool]($hideTerms)) 'userType' = "$usertype" - 'skipKeyboardSelectionPage' = $([bool]($Autokeyboard)) + 'keyboardSelectionPageSkipped' = $([bool]($Autokeyboard)) } } $Body = ConvertTo-Json -InputObject $ObjBody diff --git a/Modules/CIPPCore/Public/Set-CIPPMailboxRule.ps1 b/Modules/CIPPCore/Public/Set-CIPPMailboxRule.ps1 new file mode 100644 index 000000000000..cbbd39cd0916 --- /dev/null +++ b/Modules/CIPPCore/Public/Set-CIPPMailboxRule.ps1 @@ -0,0 +1,34 @@ +function Set-CIPPMailboxRule { + [CmdletBinding()] + param ( + $UserId, + $Username, + $TenantFilter, + $APIName = 'Set mailbox rules', + $Headers, + $RuleId, + $RuleName, + [switch]$Enable, + [switch]$Disable + ) + + if ($Enable.IsPresent -eq $true) { + $State = 'Enable' + } elseif ($Disable.IsPresent -eq $true) { + $State = 'Disable' + } else { + Write-LogMessage -headers $Headers -API $APIName -message 'No state provided for mailbox rule' -Sev 'Error' -tenant $TenantFilter + throw 'No state provided for mailbox rule' + } + + try { + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet "$State-InboxRule" -Anchor $Username -cmdParams @{Identity = $RuleId } + Write-LogMessage -headers $Headers -API $APIName -message "Successfully set mailbox rule $($RuleName) for $($Username) to $($State)d" -Sev 'Info' -tenant $TenantFilter + return "Successfully set mailbox rule $($RuleName) for $($Username) to $($State)d" + } catch { + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -headers $Headers -API $APIName -message "Could not set mailbox rule $($RuleName) for $($Username) to $($State)d. Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + throw "Could not set mailbox rule $($RuleName) for $($Username) to $($State)d. Error: $($ErrorMessage.NormalizedError)" + } + +} diff --git a/Modules/CIPPCore/Public/Set-CIPPSAMAdminRoles.ps1 b/Modules/CIPPCore/Public/Set-CIPPSAMAdminRoles.ps1 index 46eddbd432fd..e5063c0ecc62 100644 --- a/Modules/CIPPCore/Public/Set-CIPPSAMAdminRoles.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPSAMAdminRoles.ps1 @@ -32,9 +32,9 @@ function Set-CIPPSAMAdminRoles { } if (($SAMRoles | Measure-Object).count -gt 0 -and $Tenants -contains $TenantFilter -or $Tenants -contains 'AllTenants') { - $AppMemberOf = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/servicePrincipals(appId='$($ENV:ApplicationID)')/memberOf/#microsoft.graph.directoryRole" -tenantid $TenantFilter -AsApp $true + $AppMemberOf = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/servicePrincipals(appId='$($env:ApplicationID)')/memberOf/#microsoft.graph.directoryRole" -tenantid $TenantFilter -AsApp $true - $sp = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/servicePrincipals(appId='$($ENV:ApplicationID)')?`$select=id,displayName" -tenantid $TenantFilter -AsApp $true) + $sp = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/servicePrincipals(appId='$($env:ApplicationID)')?`$select=id,displayName" -tenantid $TenantFilter -AsApp $true) $id = $sp.id $Requests = $SAMRoles | Where-Object { $AppMemberOf.roleTemplateId -notcontains $_.value } | ForEach-Object { @@ -54,13 +54,13 @@ function Set-CIPPSAMAdminRoles { if (($Requests | Measure-Object).count -gt 0) { $HasFailures = $false try { - $null = New-ExoRequest -cmdlet 'New-ServicePrincipal' -cmdParams @{AppId = $ENV:ApplicationID; ObjectId = $id; DisplayName = 'CIPP-SAM' } -Compliance -tenantid $TenantFilter -useSystemMailbox $true -AsApp + $null = New-ExoRequest -cmdlet 'New-ServicePrincipal' -cmdParams @{AppId = $env:ApplicationID; ObjectId = $id; DisplayName = 'CIPP-SAM' } -Compliance -tenantid $TenantFilter -useSystemMailbox $true -AsApp $ActionLogs.Add('Added Service Principal to Compliance Center') } catch { $ActionLogs.Add('Service Principal already added to Compliance Center') } try { - $null = New-ExoRequest -cmdlet 'New-ServicePrincipal' -cmdParams @{AppId = $ENV:ApplicationID; ObjectId = $id; DisplayName = 'CIPP-SAM' } -tenantid $TenantFilter -useSystemMailbox $true -AsApp + $null = New-ExoRequest -cmdlet 'New-ServicePrincipal' -cmdParams @{AppId = $env:ApplicationID; ObjectId = $id; DisplayName = 'CIPP-SAM' } -tenantid $TenantFilter -useSystemMailbox $true -AsApp $ActionLogs.Add('Added Service Principal to Exchange Online') } catch { $ActionLogs.Add('Service Principal already added to Exchange Online') diff --git a/Modules/CIPPCore/Public/Set-CIPPSherwebLicense.ps1 b/Modules/CIPPCore/Public/Set-CIPPSherwebLicense.ps1 new file mode 100644 index 000000000000..fb71de2ea786 --- /dev/null +++ b/Modules/CIPPCore/Public/Set-CIPPSherwebLicense.ps1 @@ -0,0 +1,15 @@ +function Set-CIPPSherwebLicense { + param ( + [Parameter(Mandatory = $true)] + [string]$tenantFilter, + + [Parameter(Mandatory = $true)] + [string]$SKUid, + + [int]$Quantity, + [int]$Add, + [int]$Remove + ) + + Set-SherwebSubscription -SKU $SKUid -Quantity $Quantity -Add $Add -Remove $Remove -TenantFilter $tenantFilter +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAnonReportDisable.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAnonReportDisable.ps1 index 9b5af33c4306..496859c365a5 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAnonReportDisable.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAnonReportDisable.ps1 @@ -57,8 +57,8 @@ function Invoke-CIPPStandardAnonReportDisable { } } if ($Settings.report -eq $true) { - $stateisCorrrect = $CurrentInfo.displayConcealedNames ? $false : $true - Set-CIPPStandardsCompareField -FieldName 'standards.AnonReportDisable' -FieldValue $stateisCorrrect -TenantFilter $tenant + $StateIsCorrect = $CurrentInfo.displayConcealedNames ? $false : $true + Set-CIPPStandardsCompareField -FieldName 'standards.AnonReportDisable' -FieldValue $StateIsCorrect -TenantFilter $tenant Add-CIPPBPAField -FieldName 'AnonReport' -FieldValue $CurrentInfo.displayConcealedNames -StoreAs bool -Tenant $tenant } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 index 3e374dbe911a..deb7eddd23bc 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 @@ -7,8 +7,8 @@ function Invoke-CIPPStandardAntiPhishPolicy { .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. + (Helptext) This creates a Anti-Phishing policy that automatically enables Mailbox Intelligence and spoofing, optional switches for Mail tips. + (DocsDescription) This creates a Anti-Phishing policy that automatically enables Mailbox Intelligence and spoofing, optional switches for Mail tips. .NOTES CAT Defender Standards @@ -40,7 +40,7 @@ function Invoke-CIPPStandardAntiPhishPolicy { ADDEDDATE 2024-03-25 POWERSHELLEQUIVALENT - Set-AntiphishPolicy or New-AntiphishPolicy + Set-AntiPhishPolicy or New-AntiPhishPolicy RECOMMENDEDBY "CIS" UPDATECOMMENTBLOCK @@ -124,7 +124,7 @@ function Invoke-CIPPStandardAntiPhishPolicy { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Anti-phishing policy already correctly configured' -sev Info } else { if ($MDOLicensed) { - $cmdparams = @{ + $cmdParams = @{ Enabled = $true PhishThresholdLevel = $Settings.PhishThresholdLevel EnableMailboxIntelligence = $true @@ -147,7 +147,7 @@ function Invoke-CIPPStandardAntiPhishPolicy { EnableOrganizationDomainsProtection = $true } } else { - $cmdparams = @{ + $cmdParams = @{ Enabled = $true EnableSpoofIntelligence = $true EnableFirstContactSafetyTips = $Settings.EnableFirstContactSafetyTips @@ -160,16 +160,16 @@ function Invoke-CIPPStandardAntiPhishPolicy { if ($CurrentState.Name -eq $PolicyName) { try { - $cmdparams.Add('Identity', $PolicyName) - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-AntiPhishPolicy' -cmdparams $cmdparams -UseSystemMailbox $true + $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 + $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 $_ @@ -178,27 +178,27 @@ function Invoke-CIPPStandardAntiPhishPolicy { } if ($RuleStateIsCorrect -eq $false) { - $cmdparams = @{ + $cmdParams = @{ Priority = 0 RecipientDomainIs = $AcceptedDomains.Name } if ($RuleState.AntiPhishPolicy -ne $PolicyName) { - $cmdparams.Add('AntiPhishPolicy', $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 + $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 + $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 $_ diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 index 929473191113..14b1a578b0c8 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 @@ -48,14 +48,14 @@ function Invoke-CIPPStandardAtpPolicyForO365 { if ($StateIsCorrect -eq $true) { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Atp Policy For O365 already set.' -sev Info } else { - $cmdparams = @{ + $cmdParams = @{ EnableATPForSPOTeamsODB = $true EnableSafeDocs = $true AllowSafeDocsOpen = $Settings.AllowSafeDocsOpen } try { - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-AtpPolicyForO365' -cmdparams $cmdparams -UseSystemMailbox $true + 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 diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoAddProxy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoAddProxy.ps1 index 51b3d978687d..5b2e1186408a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoAddProxy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoAddProxy.ps1 @@ -23,7 +23,7 @@ function Invoke-CIPPStandardAutoAddProxy { Set-Mailbox -EmailAddresses @{add=\$EmailAddress} RECOMMENDEDBY DISABLEDFEATURES - + {"report":true,"warn":true,"remediate":false} UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotProfile.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotProfile.ps1 index 4ba2b95ea71b..7812954bc9ec 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotProfile.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotProfile.ps1 @@ -14,7 +14,7 @@ function Invoke-CIPPStandardAutopilotProfile { Device Management Standards TAG DISABLEDFEATURES - + {"report":true,"warn":true,"remediate":false} ADDEDCOMPONENT {"type":"textField","name":"standards.AutopilotProfile.DisplayName","label":"Profile Display Name"} {"type":"textField","name":"standards.AutopilotProfile.Description","label":"Profile Description"} @@ -82,16 +82,17 @@ function Invoke-CIPPStandardAutopilotProfile { description = $settings.Description usertype = $usertype DeploymentMode = $DeploymentMode - assignto = $settings.Assignto + assignto = $settings.AssignToAllDevices devicenameTemplate = $Settings.DeviceNameTemplate - allowWhiteGlove = $Settings.allowWhiteglove + allowWhiteGlove = $Settings.AllowWhiteGlove CollectHash = $Settings.CollectHash hideChangeAccount = $Settings.HideChangeAccount hidePrivacy = $Settings.HidePrivacy hideTerms = $Settings.HideTerms - Autokeyboard = $Settings.Autokeyboard - Language = $Settings.languages.value + AutoKeyboard = $Settings.AutoKeyboard + Language = $Settings.Languages.value } + Set-CIPPDefaultAPDeploymentProfile @Parameters Write-LogMessage -API 'Standards' -tenant $tenant -message "Created Autopilot profile '$($settings.DisplayName)'" -sev Info } catch { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotStatusPage.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotStatusPage.ps1 index d0d39040c2d1..e91b53d2fd1b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotStatusPage.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotStatusPage.ps1 @@ -14,7 +14,7 @@ function Invoke-CIPPStandardAutopilotStatusPage { Device Management Standards TAG DISABLEDFEATURES - + {"report":true,"warn":true,"remediate":false} 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} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccessTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccessTemplate.ps1 index 03105df1c8b5..ca7a409b4122 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 - + {"report":true,"warn":true,"remediate":false} IMPACT High Impact ADDEDDATE diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDefaultPlatformRestrictions.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDefaultPlatformRestrictions.ps1 new file mode 100644 index 000000000000..a29474ce86f9 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDefaultPlatformRestrictions.ps1 @@ -0,0 +1,137 @@ +function Invoke-CIPPStandardDefaultPlatformRestrictions { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) DefaultPlatformRestrictions + .SYNOPSIS + (Label) Device enrollment restrictions + .DESCRIPTION + (Helptext) Sets the default platform restrictions for enrolling devices into Intune. Note: Do not block personally owned if platform is blocked. + (DocsDescription) Sets the default platform restrictions for enrolling devices into Intune. Note: Do not block personally owned if platform is blocked. + .NOTES + CAT + Intune Standards + TAG + ADDEDCOMPONENT + {"type":"switch","name":"standards.DefaultPlatformRestrictions.platformAndroidForWorkBlocked","label":"Block platform Android Enterprise (work profile)","default":false} + {"type":"switch","name":"standards.DefaultPlatformRestrictions.personalAndroidForWorkBlocked","label":"Block personally owned Android Enterprise (work profile)","default":false} + {"type":"switch","name":"standards.DefaultPlatformRestrictions.platformAndroidBlocked","label":"Block platform Android","default":false} + {"type":"switch","name":"standards.DefaultPlatformRestrictions.personalAndroidBlocked","label":"Block personally owned Android","default":false} + {"type":"switch","name":"standards.DefaultPlatformRestrictions.platformiOSBlocked","label":"Block platform iOS","default":false} + {"type":"switch","name":"standards.DefaultPlatformRestrictions.personaliOSBlocked","label":"Block personally owned iOS","default":false} + {"type":"switch","name":"standards.DefaultPlatformRestrictions.platformMacOSBlocked","label":"Block platform macOS","default":false} + {"type":"switch","name":"standards.DefaultPlatformRestrictions.personalMacOSBlocked","label":"Block personally owned macOS","default":false} + {"type":"switch","name":"standards.DefaultPlatformRestrictions.platformWindowsBlocked","label":"Block platform Windows","default":false} + {"type":"switch","name":"standards.DefaultPlatformRestrictions.personalWindowsBlocked","label":"Block personally owned Windows","default":false} + IMPACT + Low Impact + ADDEDDATE + 2025-04-01 + 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) + + try { + $CurrentState = New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/deviceManagement/deviceEnrollmentConfigurations?`$expand=assignments&orderBy=priority&`$filter=deviceEnrollmentConfigurationType eq 'SinglePlatformRestriction'" -tenantID $Tenant -AsApp $true | + Select-Object -Property id, androidForWorkRestriction, androidRestriction, iosRestriction, macOSRestriction, windowsRestriction + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Could not get the DefaultPlatformRestrictions for $Tenant. This tenant might not have premium licenses available: $ErrorMessage" -Sev Error + } + + $StateIsCorrect = ($CurrentState.androidForWorkRestriction.platformBlocked -eq $Settings.platformAndroidForWorkBlocked) -and + ($CurrentState.androidForWorkRestriction.personalDeviceEnrollmentBlocked -eq $Settings.personalAndroidForWorkBlocked) -and + ($CurrentState.androidRestriction.platformBlocked -eq $Settings.platformAndroidBlocked) -and + ($CurrentState.androidRestriction.personalDeviceEnrollmentBlocked -eq $Settings.personalAndroidBlocked) -and + ($CurrentState.iosRestriction.platformBlocked -eq $Settings.platformiOSBlocked) -and + ($CurrentState.iosRestriction.personalDeviceEnrollmentBlocked -eq $Settings.personaliOSBlocked) -and + ($CurrentState.macOSRestriction.platformBlocked -eq $Settings.platformMacOSBlocked) -and + ($CurrentState.macOSRestriction.personalDeviceEnrollmentBlocked -eq $Settings.personalMacOSBlocked) -and + ($CurrentState.windowsRestriction.platformBlocked -eq $Settings.platformWindowsBlocked) -and + ($CurrentState.windowsRestriction.personalDeviceEnrollmentBlocked -eq $Settings.personalWindowsBlocked) + + If ($Settings.remediate -eq $true) { + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'DefaultPlatformRestrictions is already applied correctly.' -Sev Info + } else { + $cmdParam = @{ + tenantid = $Tenant + uri = "https://graph.microsoft.com/beta/deviceManagement/deviceEnrollmentConfigurations/$($CurrentState.id)" + AsApp = $false + Type = 'PATCH' + ContentType = 'application/json; charset=utf-8' + Body = [PSCustomObject]@{ + "@odata.type" = "#microsoft.graph.deviceEnrollmentPlatformRestrictionsConfiguration" + androidForWorkRestriction = [PSCustomObject]@{ + "@odata.type" = "microsoft.graph.deviceEnrollmentPlatformRestriction" + platformBlocked = $Settings.platformAndroidForWorkBlocked + personalDeviceEnrollmentBlocked = $Settings.personalAndroidForWorkBlocked + } + androidRestriction = [PSCustomObject]@{ + "@odata.type" = "microsoft.graph.deviceEnrollmentPlatformRestriction" + platformBlocked = $Settings.platformAndroidBlocked + personalDeviceEnrollmentBlocked = $Settings.personalAndroidBlocked + } + iosRestriction = [PSCustomObject]@{ + "@odata.type" = "microsoft.graph.deviceEnrollmentPlatformRestriction" + platformBlocked = $Settings.platformiOSBlocked + personalDeviceEnrollmentBlocked = $Settings.personaliOSBlocked + } + macOSRestriction = [PSCustomObject]@{ + "@odata.type" = "microsoft.graph.deviceEnrollmentPlatformRestriction" + platformBlocked = $Settings.platformMacOSBlocked + personalDeviceEnrollmentBlocked = $Settings.personalMacOSBlocked + } + windowsRestriction = [PSCustomObject]@{ + "@odata.type" = "microsoft.graph.deviceEnrollmentPlatformRestriction" + platformBlocked = $Settings.platformWindowsBlocked + personalDeviceEnrollmentBlocked = $Settings.personalWindowsBlocked + } + } | ConvertTo-Json -Compress -Depth 10 + } + try { + $null = New-GraphPostRequest @cmdParam + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully updated DefaultPlatformRestrictions.' -Sev Info + } catch { + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to update DefaultPlatformRestrictions. Error: $($ErrorMessage.NormalizedError)" -Sev Error + } + } + + } + + If ($Settings.alert -eq $true) { + + if ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'DefaultPlatformRestrictions is correctly set.' -Sev Info + } else { + Write-StandardsAlert -message 'DefaultPlatformRestrictions is incorrectly set.' -object $StateIsCorrect -tenant $Tenant -standardName 'DefaultPlatformRestrictions' -standardId $Settings.standardId + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'DefaultPlatformRestrictions is incorrectly set.' -Sev Info + } + } + + If ($Settings.report -eq $true) { + $Table = [PSCustomObject]@{ + platformAndroidForWorkBlocked = $CurrentState.androidForWorkRestriction.platformBlocked + personalAndroidForWorkBlocked = $CurrentState.androidForWorkRestriction.personalDeviceEnrollmentBlocked + platformAndroidBlocked = $CurrentState.androidRestriction.platformBlocked + personalAndroidBlocked = $CurrentState.androidRestriction.personalDeviceEnrollmentBlocked + platformiOSBlocked = $CurrentState.iosRestriction.platformBlocked + personaliOSBlocked = $CurrentState.iosRestriction.personalDeviceEnrollmentBlocked + platformMacOSBlocked = $CurrentState.macOSRestriction.platformBlocked + personalMacOSBlocked = $CurrentState.macOSRestriction.personalDeviceEnrollmentBlocked + platformWindowsBlocked = $CurrentState.windowsRestriction.platformBlocked + personalWindowsBlocked = $CurrentState.windowsRestriction.personalDeviceEnrollmentBlocked + } + Set-CIPPStandardsCompareField -FieldName 'standards.DefaultPlatformRestrictions' -FieldValue $Table -TenantFilter $Tenant + Add-CIPPBPAField -FieldName 'DefaultPlatformRestrictions' -FieldValue [bool]$StateIsCorrect -StoreAs bool -Tenant $Tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 index edb8573df599..d4171ac615fd 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 @@ -33,11 +33,6 @@ function Invoke-CIPPStandardDisableAddShortcutsToOneDrive { $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | Select-Object _ObjectIdentity_, TenantFilter, DisableAddToOneDrive - if ($Settings.report -eq $true) { - Set-CIPPStandardsCompareField -FieldName 'standards.DisableAddShortcutsToOneDrive' -FieldValue $CurrentState.DisableAddToOneDrive -TenantFilter $Tenant - Add-CIPPBPAField -FieldName 'OneDriveAddShortcutButtonDisabled' -FieldValue $CurrentState.DisableAddToOneDrive -StoreAs bool -Tenant $Tenant - } - # Input validation $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)) { @@ -49,6 +44,16 @@ function Invoke-CIPPStandardDisableAddShortcutsToOneDrive { $StateIsCorrect = if ($CurrentState.DisableAddToOneDrive -eq $WantedState) { $true } else { $false } $HumanReadableState = if ($WantedState -eq $true) { 'disabled' } else { 'enabled' } + if ($Settings.report -eq $true) { + if ($StateIsCorrect -eq $true) { + $FieldValue = $true + } else { + $FieldValue = $CurrentState | Select-Object -Property DisableAddToOneDrive + } + Set-CIPPStandardsCompareField -FieldName 'standards.DisableAddShortcutsToOneDrive' -FieldValue $FieldValue -TenantFilter $Tenant + Add-CIPPBPAField -FieldName 'OneDriveAddShortcutButtonDisabled' -FieldValue $CurrentState.DisableAddToOneDrive -StoreAs bool -Tenant $Tenant + } + If ($Settings.remediate -eq $true) { Write-Host 'Time to remediate' diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 index c994e417ffcc..0f6f6829f9af 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 @@ -47,8 +47,8 @@ function Invoke-CIPPStandardDisableOutlookAddins { foreach ($Role in $RolesToRemove) { try { - New-ExoRequest -tenantid $Tenant -cmdlet 'Get-ManagementRoleAssignment' -cmdparams @{ RoleAssignee = $CurrentInfo.Identity; Role = $Role } | ForEach-Object { - New-ExoRequest -tenantid $Tenant -cmdlet 'Remove-ManagementRoleAssignment' -cmdparams @{ Identity = $_.Guid; Confirm = $false } -UseSystemMailbox $true + New-ExoRequest -tenantid $Tenant -cmdlet 'Get-ManagementRoleAssignment' -cmdParams @{ RoleAssignee = $CurrentInfo.Identity; Role = $Role } | ForEach-Object { + New-ExoRequest -tenantid $Tenant -cmdlet 'Remove-ManagementRoleAssignment' -cmdParams @{ Identity = $_.Guid; Confirm = $false } -UseSystemMailbox $true Write-LogMessage -API 'Standards' -tenant $tenant -message "Disabled Outlook add-in role: $Role" -sev Debug } } catch { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 index 3e6a98fba54b..95c2ece96ddd 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 @@ -5,7 +5,7 @@ function Invoke-CIPPStandardDisableReshare { .COMPONENT (APIName) DisableReshare .SYNOPSIS - (Label) Disable Resharing by External Users + (Label) Disable Re-sharing by External Users .DESCRIPTION (Helptext) Disables the ability for external users to share files they don't own. Sharing links can only be made for People with existing access (DocsDescription) Disables the ability for external users to share files they don't own. Sharing links can only be made for People with existing access. This is a tenant wide setting and overrules any settings set on the site level diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 index f7f1502a69e7..589832537c7d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 @@ -38,7 +38,7 @@ function Invoke-CIPPStandardDisableTNEF { if ($CurrentState.TNEFEnabled -ne $false) { try { - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-RemoteDomain' -cmdParams @{Identity = 'Default'; TNEFEnabled = $false } -useSystemmailbox $true + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-RemoteDomain' -cmdParams @{Identity = 'Default'; TNEFEnabled = $false } -useSystemMailbox $true Write-LogMessage -API 'Standards' -tenant $tenant -message 'Disabled TNEF for Default Remote Domain' -sev Info } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTenantCreation.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTenantCreation.ps1 index 73059a3f91bf..835cec11cd10 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTenantCreation.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTenantCreation.ps1 @@ -7,7 +7,7 @@ function Invoke-CIPPStandardDisableTenantCreation { .SYNOPSIS (Label) Disable M365 Tenant creation by users .DESCRIPTION - (Helptext) Restricts creation of M365 tenants to the Global Administrator or Tenant Creator roles. + (Helptext) Restricts creation of M365 tenants to the Global Administrator or Tenant Creator roles. (DocsDescription) Users by default are allowed to create M365 tenants. This disables that so only admins can create new M365 tenants. .NOTES CAT diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableViva.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableViva.ps1 index b1302a56bec3..ba8661834447 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableViva.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableViva.ps1 @@ -7,8 +7,8 @@ function Invoke-CIPPStandardDisableViva { .SYNOPSIS (Label) Disable daily Insight/Viva reports .DESCRIPTION - (Helptext) Disables the daily viva reports for all users. - (DocsDescription) Disables the daily viva reports for all users. + (Helptext) Disables the daily viva reports for all users. This standard requires the CIPP-SAM application to have the Company Administrator (Global Admin) role in the tenant. Enable this using CIPP > Advanced > Super Admin > SAM App Roles. Activate the roles with a CPV refresh. + (DocsDescription) Disables the daily viva reports for all users. This standard requires the CIPP-SAM application to have the Company Administrator (Global Admin) role in the tenant. Enable this using CIPP \> Advanced \> Super Admin \> SAM App Roles. Activate the roles with a CPV refresh. .NOTES CAT Exchange Standards diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 index 8fe6b14885d4..2d8736b335c9 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 @@ -35,13 +35,13 @@ function Invoke-CIPPStandardEXODisableAutoForwarding { param($Tenant, $Settings) ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'EXODisableAutoForwarding' - $CurrentInfo = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-HostedOutboundSpamFilterPolicy' -cmdparams @{Identity = 'Default' } -useSystemMailbox $true + $CurrentInfo = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-HostedOutboundSpamFilterPolicy' -cmdParams @{Identity = 'Default' } -useSystemMailbox $true $StateIsCorrect = $CurrentInfo.AutoForwardingMode -eq 'Off' If ($Settings.remediate -eq $true) { try { - New-ExoRequest -tenantid $tenant -cmdlet 'Set-HostedOutboundSpamFilterPolicy' -cmdparams @{ Identity = 'Default'; AutoForwardingMode = 'Off' } -useSystemMailbox $true + New-ExoRequest -tenantid $tenant -cmdlet 'Set-HostedOutboundSpamFilterPolicy' -cmdParams @{ Identity = 'Default'; AutoForwardingMode = 'Off' } -useSystemMailbox $true Write-LogMessage -API 'Standards' -tenant $tenant -message 'Disabled auto forwarding' -sev Info } catch { $ErrorMessage = Get-CippException -Exception $_ diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableLitigationHold.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableLitigationHold.ps1 index b543ef58a25a..e80b6077345c 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableLitigationHold.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableLitigationHold.ps1 @@ -14,6 +14,7 @@ function Invoke-CIPPStandardEnableLitigationHold { Exchange Standards TAG ADDEDCOMPONENT + {"type":"textField","name":"standards.EnableLitigationHold.days","required":false,"label":"Days to apply for litigation hold"} IMPACT Low Impact ADDEDDATE @@ -30,7 +31,7 @@ function Invoke-CIPPStandardEnableLitigationHold { param($Tenant, $Settings) ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'EnableLitigationHold' - $MailboxesNoLitHold = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-Mailbox' -cmdparams @{ Filter = 'LitigationHoldEnabled -eq "False"' } -Select 'UserPrincipalName,PersistedCapabilities,LitigationHoldEnabled' | Where-Object { $_.PersistedCapabilities -contains 'BPOS_S_DlpAddOn' -or $_.PersistedCapabilities -contains 'BPOS_S_Enterprise' } + $MailboxesNoLitHold = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-Mailbox' -cmdParams @{ Filter = 'LitigationHoldEnabled -eq "False"' } -Select 'UserPrincipalName,PersistedCapabilities,LitigationHoldEnabled' | Where-Object { $_.PersistedCapabilities -contains 'BPOS_S_DlpAddOn' -or $_.PersistedCapabilities -contains 'BPOS_S_Enterprise' } if ($Settings.remediate -eq $true) { if ($null -eq $MailboxesNoLitHold) { @@ -44,19 +45,19 @@ function Invoke-CIPPStandardEnableLitigationHold { Parameters = @{ Identity = $_.UserPrincipalName; LitigationHoldEnabled = $true } } } - if ($Settings.days -ne $null) { + if ($null -ne $Settings.days) { $params.CmdletInput.Parameters['LitigationHoldDuration'] = $Settings.days } $params } - $BatchResults = New-ExoBulkRequest -tenantid $tenant -cmdletArray @($Request) + $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 + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to Enable Litigation Hold for $($_.Target). Error: $ErrorMessage" -sev Error } } } catch { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 index 32266151d8a2..b4671d72e7ea 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 @@ -44,7 +44,7 @@ function Invoke-CIPPStandardEnableMailTips { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'All MailTips are already enabled.' -sev Info } else { try { - New-ExoRequest -useSystemMailbox $true -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdparams @{ MailTipsAllTipsEnabled = $true; MailTipsExternalRecipientsTipsEnabled = $true; MailTipsGroupMetricsEnabled = $true; MailTipsLargeAudienceThreshold = $Settings.MailTipsLargeAudienceThreshold } + New-ExoRequest -useSystemMailbox $true -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdParams @{ MailTipsAllTipsEnabled = $true; MailTipsExternalRecipientsTipsEnabled = $true; MailTipsGroupMetricsEnabled = $true; MailTipsLargeAudienceThreshold = $Settings.MailTipsLargeAudienceThreshold } Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Enabled all MailTips' -sev Info } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 index e0d71e06bc25..8e7bfae1e5cf 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 @@ -32,7 +32,7 @@ function Invoke-CIPPStandardEnableOnlineArchiving { $MailboxPlans = @( 'ExchangeOnline', 'ExchangeOnlineEnterprise' ) $MailboxesNoArchive = $MailboxPlans | ForEach-Object { - New-ExoRequest -tenantid $Tenant -cmdlet 'Get-Mailbox' -cmdparams @{ MailboxPlan = $_; Filter = 'ArchiveGuid -Eq "00000000-0000-0000-0000-000000000000" -AND RecipientTypeDetails -Eq "UserMailbox"' } + New-ExoRequest -tenantid $Tenant -cmdlet 'Get-Mailbox' -cmdParams @{ MailboxPlan = $_; Filter = 'ArchiveGuid -Eq "00000000-0000-0000-0000-000000000000" -AND RecipientTypeDetails -Eq "UserMailbox"' } Write-Host "Getting mailboxes without Online Archiving for plan $_" } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 index ca72eac437d5..f299e4762242 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 - + {"report":true,"warn":true,"remediate":false} IMPACT Medium Impact ADDEDDATE diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGuestInvite.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGuestInvite.ps1 index 5a8c6c039797..b244ebc80777 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGuestInvite.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGuestInvite.ps1 @@ -20,7 +20,7 @@ function Invoke-CIPPStandardGuestInvite { ADDEDDATE 2024-11-12 POWERSHELLEQUIVALENT - + Graph API RECOMMENDEDBY UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 index 7ca986e7a03c..2651942d5e9e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 @@ -21,7 +21,7 @@ function Invoke-CIPPStandardIntuneComplianceSettings { ADDEDDATE 2024-11-12 POWERSHELLEQUIVALENT - + Graph API RECOMMENDEDBY UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 index e92923d38336..ed04a79091bd 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 @@ -15,7 +15,7 @@ function Invoke-CIPPStandardIntuneTemplate { MULTIPLE True DISABLEDFEATURES - + {"report":false,"warn":false,"remediate":false} IMPACT High Impact ADDEDDATE @@ -24,7 +24,7 @@ function Invoke-CIPPStandardIntuneTemplate { {"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."} + {"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 @@ -35,24 +35,45 @@ function Invoke-CIPPStandardIntuneTemplate { $Table = Get-CippTable -tablename 'templates' $Filter = "PartitionKey eq 'IntuneTemplate'" $Request = @{body = $null } - + Write-Host "IntuneTemplate: Starting process. Settings are: $($Settings | ConvertTo-Json -Compress)" $CompareList = foreach ($Template in $Settings) { + Write-Host "IntuneTemplate: $($Template.TemplateList.value) - Trying to find template" $Request.body = (Get-CIPPAzDataTableEntity @Table -Filter $Filter | Where-Object -Property RowKey -Like "$($Template.TemplateList.value)*").JSON | ConvertFrom-Json -ErrorAction SilentlyContinue - if ($Request.body -eq $null) { + if ($null -eq $Request.body) { Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to find template $($Template.TemplateList.value). Has this Intune Template been deleted?" -sev 'Error' continue } + Write-Host "IntuneTemplate: $($Template.TemplateList.value) - Got template." + $displayname = $request.body.Displayname $description = $request.body.Description $RawJSON = $Request.body.RawJSON - $ExistingPolicy = Get-CIPPIntunePolicy -tenantFilter $Tenant -DisplayName $displayname -TemplateType $Request.body.Type + try { + Write-Host "IntuneTemplate: $($Template.TemplateList.value) - Grabbing existing Policy" + $ExistingPolicy = Get-CIPPIntunePolicy -tenantFilter $Tenant -DisplayName $displayname -TemplateType $Request.body.Type + } catch { + Write-Host "IntuneTemplate: $($Template.TemplateList.value) - Failed to get existing." + } if ($ExistingPolicy) { - $RawJSON = Get-CIPPTextReplacement -Text $RawJSON -TenantFilter $Tenant - $JSONExistingPolicy = $ExistingPolicy.cippconfiguration | ConvertFrom-Json - $JSONTemplate = $RawJSON | ConvertFrom-Json - $Compare = Compare-CIPPIntuneObject -ReferenceObject $JSONTemplate -DifferenceObject $JSONExistingPolicy -compareType $Request.body.Type + try { + Write-Host "IntuneTemplate: $($Template.TemplateList.value) - Found existing policy." + $RawJSON = Get-CIPPTextReplacement -Text $RawJSON -TenantFilter $Tenant + Write-Host "IntuneTemplate: $($Template.TemplateList.value) - Grabbing JSON existing." + $JSONExistingPolicy = $ExistingPolicy.cippconfiguration | ConvertFrom-Json + Write-Host "IntuneTemplate: $($Template.TemplateList.value) - Got existing JSON. Converting RawJSON to Template" + $JSONTemplate = $RawJSON | ConvertFrom-Json + Write-Host "IntuneTemplate: $($Template.TemplateList.value) - Converted RawJSON to Template." + Write-Host "IntuneTemplate: $($Template.TemplateList.value) - Comparing JSON." + $Compare = Compare-CIPPIntuneObject -ReferenceObject $JSONTemplate -DifferenceObject $JSONExistingPolicy -compareType $Request.body.Type -ErrorAction SilentlyContinue + } catch { + Write-Host "The compare failed. The error was: $($_.Exception.Message)" + } + Write-Host "IntuneTemplate: $($Template.TemplateList.value) - Compared JSON: $($Compare | ConvertTo-Json -Compress)" + } else { + Write-Host "IntuneTemplate: $($Template.TemplateList.value) - No existing policy found." } if ($Compare) { + Write-Host "IntuneTemplate: $($Template.TemplateList.value) - Compare found differences." [PSCustomObject]@{ MatchFailed = $true displayname = $displayname @@ -65,8 +86,10 @@ function Invoke-CIPPStandardIntuneTemplate { remediate = $Template.remediate existingPolicyId = $ExistingPolicy.id templateId = $Template.TemplateList.value + customGroup = $Template.customGroup } } else { + Write-Host "IntuneTemplate: $($Template.TemplateList.value) - No differences found." [PSCustomObject]@{ MatchFailed = $false displayname = $displayname @@ -79,6 +102,7 @@ function Invoke-CIPPStandardIntuneTemplate { remediate = $Template.remediate existingPolicyId = $ExistingPolicy.id templateId = $Template.TemplateList.value + customGroup = $Template.customGroup } } } @@ -86,7 +110,7 @@ function Invoke-CIPPStandardIntuneTemplate { If ($true -in $Settings.remediate) { Write-Host 'starting template deploy' foreach ($TemplateFile in $CompareList | Where-Object -Property remediate -EQ $true) { - Write-Host "working on template deploy: $($Template.displayname)" + Write-Host "working on template deploy: $($TemplateFile.displayname)" try { $TemplateFile.customGroup ? ($TemplateFile.AssignTo = $TemplateFile.customGroup) : $null Set-CIPPIntunePolicy -TemplateType $TemplateFile.body.Type -Description $TemplateFile.description -DisplayName $TemplateFile.displayname -RawJSON $templateFile.rawJSON -AssignTo $TemplateFile.AssignTo -ExcludeGroup $TemplateFile.excludeGroup -tenantFilter $Tenant diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 index ad447c2a6288..d5044ec3e36a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 @@ -96,7 +96,7 @@ function Invoke-CIPPStandardMalwareFilterPolicy { if ($StateIsCorrect -eq $true) { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Malware Filter Policy already correctly configured' -sev Info } else { - $cmdparams = @{ + $cmdParams = @{ EnableFileFilter = $true FileTypes = $ExpectedFileTypes FileTypeAction = $Settings.FileTypeAction @@ -110,16 +110,16 @@ function Invoke-CIPPStandardMalwareFilterPolicy { if ($CurrentState.Name -eq $PolicyName) { try { - $cmdparams.Add('Identity', $PolicyName) - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-MalwareFilterPolicy' -cmdparams $cmdparams -UseSystemMailbox $true + $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 + $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 $_ @@ -128,27 +128,27 @@ function Invoke-CIPPStandardMalwareFilterPolicy { } if ($RuleStateIsCorrect -eq $false) { - $cmdparams = @{ + $cmdParams = @{ Priority = 0 RecipientDomainIs = $AcceptedDomains.Name } if ($RuleState.MalwareFilterPolicy -ne $PolicyName) { - $cmdparams.Add('MalwareFilterPolicy', $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 + $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 + $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 $_ diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 index e9fde585ffe1..f53d2a3b0762 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 @@ -43,7 +43,7 @@ function Invoke-CIPPStandardOauthConsent { $Existing = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/policies/permissionGrantPolicies/' -tenantid $tenant) | Where-Object -Property id -EQ 'cipp-consent-policy' if (!$Existing) { New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/permissionGrantPolicies' -Type POST -Body '{ "id":"cipp-consent-policy", "displayName":"Application Consent Policy", "description":"This policy controls the current application consent policies."}' -ContentType 'application/json' - #Replaced static web app appid with Office 365 Management by Microsofts recommendation; this application is always consented, cannot be removed nor elevated as the portals run on this app id. + #Replaced static web app appid with Office 365 Management by Microsoft's recommendation; this application is always consented, cannot be removed nor elevated as the portals run on this app id. New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/permissionGrantPolicies/cipp-consent-policy/includes' -Type POST -Body '{"permissionClassification":"all","permissionType":"delegated","clientApplicationIds":["00b41c95-dab0-4487-9791-b9d2c32c80f2"]}' -ContentType 'application/json' } try { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOutBoundSpamAlert.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOutBoundSpamAlert.ps1 index 9c28667cd0f1..ee8cbd3db58a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOutBoundSpamAlert.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOutBoundSpamAlert.ps1 @@ -39,7 +39,7 @@ function Invoke-CIPPStandardOutBoundSpamAlert { if ($CurrentInfo.NotifyOutboundSpam -ne $true -or $CurrentInfo.NotifyOutboundSpamRecipients -ne $settings.OutboundSpamContact) { $Contacts = $settings.OutboundSpamContact try { - New-ExoRequest -tenantid $tenant -cmdlet 'Set-HostedOutboundSpamFilterPolicy' -cmdparams @{ Identity = 'Default'; NotifyOutboundSpam = $true; NotifyOutboundSpamRecipients = $Contacts } -useSystemMailbox $true + New-ExoRequest -tenantid $tenant -cmdlet 'Set-HostedOutboundSpamFilterPolicy' -cmdParams @{ Identity = 'Default'; NotifyOutboundSpam = $true; NotifyOutboundSpamRecipients = $Contacts } -useSystemMailbox $true Write-LogMessage -API 'Standards' -tenant $tenant -message "Set outbound spam filter alert to $($Contacts)" -sev Info } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 index 575a03854ee0..0fbabebf7ef0 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPWcompanionAppAllowedState.ps1 @@ -36,7 +36,8 @@ function Invoke-CIPPStandardPWcompanionAppAllowedState { # Get state value using null-coalescing operator - $state = $Settings.state.value ?? $Settings.state + $state = $Settings.state.value ? $Settings.state.value : $settings.state + $authState = if ($authenticatorFeaturesState.featureSettings.companionAppAllowedState.state -eq $state) { $true } else { $false } # Input validation if (([string]::IsNullOrWhiteSpace($state) -or $state -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 index 17ce2b2835f4..c2db0ebf36e1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPasswordExpireDisabled.ps1 @@ -34,12 +34,12 @@ function Invoke-CIPPStandardPasswordExpireDisabled { param($Tenant, $Settings) $GraphRequest = New-GraphGetRequest -uri 'https://graph.microsoft.com/v1.0/domains' -tenantid $Tenant - $DomainswithoutPassExpire = $GraphRequest | Where-Object -Property passwordValidityPeriodInDays -NE '2147483647' + $DomainsWithoutPassExpire = $GraphRequest | Where-Object -Property passwordValidityPeriodInDays -NE '2147483647' if ($Settings.remediate -eq $true) { - if ($DomainswithoutPassExpire) { - $DomainswithoutPassExpire | ForEach-Object { + if ($DomainsWithoutPassExpire) { + $DomainsWithoutPassExpire | ForEach-Object { try { if ( $null -eq $_.passwordNotificationWindowInDays ) { $Body = '{"passwordValidityPeriodInDays": 2147483647, "passwordNotificationWindowInDays": 14 }' @@ -61,18 +61,18 @@ function Invoke-CIPPStandardPasswordExpireDisabled { } if ($Settings.alert -eq $true) { - if ($DomainswithoutPassExpire) { - Write-StandardsAlert -message "Password Expiration is not disabled for the following $($DomainswithoutPassExpire.Count) domains: $($DomainswithoutPassExpire.id -join ', ')" -object $DomainswithoutPassExpire -tenant $tenant -standardName 'PasswordExpireDisabled' -standardId $Settings.standardId - Write-LogMessage -API 'Standards' -tenant $tenant -message "Password Expiration is not disabled for the following $($DomainswithoutPassExpire.Count) domains: $($DomainswithoutPassExpire.id -join ', ')" -sev Info + if ($DomainsWithoutPassExpire) { + Write-StandardsAlert -message "Password Expiration is not disabled for the following $($DomainsWithoutPassExpire.Count) domains: $($DomainsWithoutPassExpire.id -join ', ')" -object $DomainsWithoutPassExpire -tenant $tenant -standardName 'PasswordExpireDisabled' -standardId $Settings.standardId + Write-LogMessage -API 'Standards' -tenant $tenant -message "Password Expiration is not disabled for the following $($DomainsWithoutPassExpire.Count) domains: $($DomainsWithoutPassExpire.id -join ', ')" -sev Info } else { Write-LogMessage -API 'Standards' -tenant $tenant -message "Password Expiration is disabled for all $($GraphRequest.Count) domains." -sev Info } } if ($Settings.report -eq $true) { - Add-CIPPBPAField -FieldName 'PasswordExpireDisabled' -FieldValue $DomainswithoutPassExpire -StoreAs json -Tenant $tenant - if ($DomainswithoutPassExpire) { - $FieldValue = $DomainswithoutPassExpire + Add-CIPPBPAField -FieldName 'PasswordExpireDisabled' -FieldValue $DomainsWithoutPassExpire -StoreAs json -Tenant $tenant + if ($DomainsWithoutPassExpire) { + $FieldValue = $DomainsWithoutPassExpire } else { $FieldValue = $true } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishProtection.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishProtection.ps1 index 6c8b19799635..6701703620a2 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishProtection.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishProtection.ps1 @@ -19,7 +19,7 @@ function Invoke-CIPPStandardPhishProtection { ADDEDDATE 2024-01-22 DISABLEDFEATURES - + {"report":true,"warn":true,"remediate":false} POWERSHELLEQUIVALENT Portal only RECOMMENDEDBY @@ -62,7 +62,7 @@ function Invoke-CIPPStandardPhishProtection { Write-LogMessage -API 'Standards' -tenant $tenant -message 'Logon Screen Phishing Protection system already active' -sev Info } else { $currentBody = $currentBody + $CSS - Write-Host 'Creating Logon Screen Phising Protection System' + Write-Host 'Creating Logon Screen Phishing Protection System' New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/organization/$($TenantId.customerId)/branding/localizations/0/customCSS" -ContentType 'text/css' -asApp $true -Type PUT -Body $currentBody Write-LogMessage -API 'Standards' -tenant $tenant -message 'Enabled Logon Screen Phishing Protection system' -sev Info @@ -82,8 +82,8 @@ function Invoke-CIPPStandardPhishProtection { } } if ($Settings.report -eq $true) { - if ($currentBody -like "*$CSS*") { $authstate = $true } else { $authstate = $false } - Add-CIPPBPAField -FieldName 'PhishProtection' -FieldValue $authstate -StoreAs bool -Tenant $tenant - Set-CIPPStandardsCompareField -FieldName 'standards.PhishProtection' -FieldValue $authstate -Tenant $tenant + if ($currentBody -like "*$CSS*") { $authState = $true } else { $authState = $false } + Add-CIPPBPAField -FieldName 'PhishProtection' -FieldValue $authState -StoreAs bool -Tenant $tenant + Set-CIPPStandardsCompareField -FieldName 'standards.PhishProtection' -FieldValue $authState -Tenant $tenant } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishSimSpoofIntelligence.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishSimSpoofIntelligence.ps1 new file mode 100644 index 000000000000..d8643a058c44 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishSimSpoofIntelligence.ps1 @@ -0,0 +1,103 @@ +function Invoke-CIPPStandardPhishSimSpoofIntelligence { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) PhishSimSpoofIntelligence + .SYNOPSIS + (Label) Add allowed domains to Spoof Intelligence + .DESCRIPTION + (Helptext) This adds allowed domains to the Spoof Intelligence Allow/Block List. + (DocsDescription) This adds allowed domains to the Spoof Intelligence Allow/Block List. + .NOTES + CAT + Defender Standards + TAG + ADDEDCOMPONENT + {"type":"autoComplete","multiple":true,"creatable":true,"required":false,"label":"Allowed Domains","name":"standards.PhishSimSpoofIntelligence.AllowedDomains"} + IMPACT + Medium Impact + ADDEDDATE + 2025-03-28 + POWERSHELLEQUIVALENT + New-TenantAllowBlockListSpoofItems + 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) + # Fetch current Phishing Simulations Spoof Intelligence domains and ensure it is correctly configured + $DomainState = New-ExoRequest -TenantId $Tenant -cmdlet 'Get-TenantAllowBlockListSpoofItems' | + Select-Object -Property Identity,SendingInfrastructure + + [String[]]$AddDomain = $Settings.AllowedDomains.value | Where-Object { $_ -notin $DomainState.SendingInfrastructure } + + $RemoveDomain = $DomainState | Where-Object { $_.SendingInfrastructure -notin $Settings.AllowedDomains.value } | + Select-Object -Property Identity,SendingInfrastructure + + $StateIsCorrect = ($AddDomain.Count -eq 0 -and $RemoveDomain.Count -eq 0) + + If ($Settings.remediate -eq $true) { + If ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -message 'Spoof Intelligence Allow list already correctly configured' -sev Info + } Else { + $BulkRequests = New-Object System.Collections.Generic.List[Hashtable] + + # Prepare removal requests + If ($RemoveDomain.Count -gt 0) { + Write-Host "Removing $($RemoveDomain.Count) domains from Spoof Intelligence" + $BulkRequests.Add(@{ + CmdletInput = @{ + CmdletName = 'Remove-TenantAllowBlockListSpoofItems' + Parameters = @{ Identity = 'default'; Ids = $RemoveDomain.Identity } + } + }) + } + + # Prepare addition requests + ForEach ($Domain in $AddDomain) { + $BulkRequests.Add(@{ + CmdletInput = @{ + CmdletName = 'New-TenantAllowBlockListSpoofItems' + Parameters = @{ Identity = 'default'; Action = 'Allow'; SendingInfrastructure = $Domain; SpoofedUser = '*'; SpoofType = 'Internal' } + } + }) + $BulkRequests.Add(@{ + CmdletInput = @{ + CmdletName = 'New-TenantAllowBlockListSpoofItems' + Parameters = @{ Identity = 'default'; Action = 'Allow'; SendingInfrastructure = $Domain; SpoofedUser = '*'; SpoofType = 'External' } + } + }) + } + $RawExoRequest = New-ExoBulkRequest -tenantid $Tenant -cmdletArray @($BulkRequests) + + $LastError = $RawExoRequest | Select-Object -Last 1 + If ($LastError.error) { + Foreach ($ExoError in $LastError.error) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to process Spoof Intelligence Domain with error: $ExoError" -Sev Error + } + } Else { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Processed all Spoof Intelligence Domains successfully." -Sev Info + } + } + } + + If ($Settings.alert -eq $true) { + If ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -message 'Spoof Intelligence Allow list is correctly configured' -sev Info + } Else { + Write-StandardsAlert -message 'Spoof Intelligence Allow list is not correctly configured' -object $CurrentState -tenant $Tenant -standardName 'PhishSimSpoofIntelligence' -standardId $Settings.standardId + Write-LogMessage -API 'Standards' -Tenant $Tenant -message 'Spoof Intelligence Allow list is not correctly configured' -sev Info + } + } + + If ($Settings.report -eq $true) { + $CurrentState = $StateIsCorrect ? $true : $DomainState.SendingInfrastructure + + Set-CIPPStandardsCompareField -FieldName 'standards.PhishSimSpoofIntelligence' -FieldValue $CurrentState -Tenant $Tenant + Add-CIPPBPAField -FieldName 'PhishSimSpoofIntelligence' -FieldValue [bool]$StateIsCorrect -StoreAs bool -Tenant $Tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishingSimulations.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishingSimulations.ps1 new file mode 100644 index 000000000000..ee792a946796 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishingSimulations.ps1 @@ -0,0 +1,174 @@ +function Invoke-CIPPStandardPhishingSimulations { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) PhishingSimulations + .SYNOPSIS + (Label) Phishing Simulation Configuration + .DESCRIPTION + (Helptext) This creates a phishing simulation policy that enables phishing simulations for the entire tenant. + (DocsDescription) This creates a phishing simulation policy that enables phishing simulations for the entire tenant. + .NOTES + CAT + Defender Standards + TAG + ADDEDCOMPONENT + {"type":"autoComplete","multiple":true,"creatable":true,"required":true,"label":"Phishing Simulation Domains","name":"standards.PhishingSimulations.Domains"} + {"type":"autoComplete","multiple":true,"creatable":true,"required":true,"label":"Phishing Simulation Sender IP Ranges","name":"standards.PhishingSimulations.SenderIpRanges"} + {"type":"autoComplete","multiple":true,"creatable":true,"required":false,"label":"Phishing Simulation Urls","name":"standards.PhishingSimulations.PhishingSimUrls"} + IMPACT + Medium Impact + ADDEDDATE + 2025-03-27 + POWERSHELLEQUIVALENT + New-TenantAllowBlockListItems, New-PhishSimOverridePolicy and New-ExoPhishSimOverrideRule + 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) + $PolicyName = 'CIPPPhishSim' + + # Fetch current Phishing Simulations Policy settings and ensure it is correctly configured + $PolicyState = New-ExoRequest -TenantId $Tenant -cmdlet 'Get-PhishSimOverridePolicy' | + Where-Object -Property Name -EQ 'PhishSimOverridePolicy' | + Select-Object -Property Identity,Name,Mode,Enabled + + $PolicyIsCorrect = ($PolicyState.Name -eq 'PhishSimOverridePolicy') -and ($PolicyState.Enabled -eq $true) + + # Fetch current Phishing Simulations Policy Rule settings and ensure it is correctly configured + $RuleState = New-ExoRequest -TenantId $Tenant -cmdlet 'Get-ExoPhishSimOverrideRule' | + Select-Object -Property Identity,Name,SenderIpRanges,Domains,SenderDomainIs + + [String[]]$AddSenderIpRanges = $Settings.SenderIpRanges.value | Where-Object { $_ -notin $RuleState.SenderIpRanges } + [String[]]$RemoveSenderIpRanges = $RuleState.SenderIpRanges | Where-Object { $_ -notin $Settings.SenderIpRanges.value } + + [String[]]$AddDomains = $Settings.Domains.value | Where-Object { $_ -notin $RuleState.Domains } + [String[]]$RemoveDomains = $RuleState.Domains | Where-Object { $_ -notin $Settings.Domains.value } + + $RuleIsCorrect = ($RuleState.Name -like "*PhishSimOverr*") -and + ($AddSenderIpRanges.Count -eq 0 -and $RemoveSenderIpRanges.Count -eq 0) -and + ($AddDomains.Count -eq 0 -and $RemoveDomains.Count -eq 0) + + # Fetch current Phishing Simulations URLs and ensure it is correctly configured + $SimUrlState = New-ExoRequest -TenantId $Tenant -cmdlet 'Get-TenantAllowBlockListItems' -cmdParams @{ListType = 'Url'; ListSubType = 'AdvancedDelivery'} | + Select-Object -Property Value + + [String[]]$AddEntries = $Settings.PhishingSimUrls.value | Where-Object { $_ -notin $SimUrlState.value } + [String[]]$RemoveEntries = $SimUrlState.value | Where-Object { $_ -notin $Settings.PhishingSimUrls.value } + + $PhishingSimUrlsIsCorrect = ($AddEntries.Count -eq 0 -and $RemoveEntries.Count -eq 0) + + # Check state for all components + $StateIsCorrect = $PolicyIsCorrect -and $RuleIsCorrect -and $PhishingSimUrlsIsCorrect + + If ($Settings.remediate -eq $true) { + If ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -message 'Advanced Phishing Simulations already correctly configured' -sev Info + } Else { + # Remediate incorrect Phishing Simulations Policy + If ($PolicyIsCorrect -eq $false) { + If ($PolicyState.Name -eq 'PhishSimOverridePolicy') { + Try { + $null = New-ExoRequest -TenantId $Tenant -cmdlet 'Set-PhishSimOverridePolicy' -cmdParams @{Identity = $PolicyName; Enabled = $true} + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Enabled Phishing Simulation override policy." -sev Info + } Catch { + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Failed to enable Phishing Simulation override policy." -sev Error -LogData $_ + } + } Else { + Try { + $null = New-ExoRequest -TenantId $Tenant -cmdlet 'New-PhishSimOverridePolicy' -cmdParams @{Name = $PolicyName; Enabled = $true} + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Created Phishing Simulation override policy." -sev Info + } Catch { + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Failed to create Phishing Simulation override policy." -sev Error -LogData $_ + } + } + } + + # Remediate incorrect Phishing Simulations Policy Rule + If ($RuleIsCorrect -eq $false) { + If ($RuleState.Name -like "*PhishSimOverr*") { + $cmdParams = @{ + Identity = $RuleState.Identity + AddSenderIpRanges = $AddSenderIpRanges + AddDomains = $AddDomains + RemoveSenderIpRanges = $RemoveSenderIpRanges + RemoveDomains = $RemoveDomains + } + Try { + $null = New-ExoRequest -TenantId $Tenant -cmdlet 'Set-ExoPhishSimOverrideRule' -cmdParams $cmdParams + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Updated Phishing Simulation override rule." -sev Info + } Catch { + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Failed to update Phishing Simulation override rule." -sev Error -LogData $_ + } + } Else { + $cmdParams = @{ + Name = $PolicyName + Policy = 'PhishSimOverridePolicy' + SenderIpRanges = $Settings.SenderIpRanges.value + Domains = $Settings.Domains.value + } + Try { + $null = New-ExoRequest -TenantId $Tenant -cmdlet 'New-ExoPhishSimOverrideRule' -cmdParams $cmdParams + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Created Phishing Simulation override rule." -sev Info + } Catch { + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Failed to create Phishing Simulation override rule." -sev Error -LogData $_ + } + } + } + + # Remediate incorrect Phishing Simulations URLs + If ($PhishingSimUrlsIsCorrect -eq $false) { + $cmdParams = @{ + ListType = 'Url' + ListSubType = 'AdvancedDelivery' + } + # Remove entries that are not in the settings + If ($RemoveEntries.Count -gt 0) { + $cmdParams.Entries = $RemoveEntries + Try { + $null = New-ExoRequest -TenantId $Tenant -cmdlet 'Remove-TenantAllowBlockListItems' -cmdParams $cmdParams + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Removed Phishing Simulation URLs from Allowlist." -sev Info + } Catch { + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Failed to remove Phishing Simulation URLs from Allowlist." -sev Error -LogData $_ + } + } + # Add entries that are in the settings + If ($AddEntries.Count -gt 0) { + $cmdParams.Entries = $AddEntries + $cmdParams.NoExpiration = $true + $cmdParams.Allow = $true + Try { + $null = New-ExoRequest -TenantId $Tenant -cmdlet 'New-TenantAllowBlockListItems' -cmdParams $cmdParams + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Added Phishing Simulation URLs to Allowlist." -sev Info + } Catch { + Write-LogMessage -API 'Standards' -Tenant $Tenant -message "Failed to add Phishing Simulation URLs to Allowlist." -sev Error -LogData $_ + } + } + } + } + } + + If ($Settings.alert -eq $true) { + If ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -message 'Phishing Simulation Configuration is correctly configured' -sev Info + } Else { + Write-StandardsAlert -message 'Phishing Simulation Configuration is not correctly configured' -object $CurrentState -tenant $Tenant -standardName 'PhishingSimulations' -standardId $Settings.standardId + Write-LogMessage -API 'Standards' -Tenant $Tenant -message 'Phishing Simulation Configuration is not correctly configured' -sev Info + } + } + + If ($Settings.report -eq $true) { + Add-CIPPBPAField -FieldName 'PhishingSimulations' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $Tenant + If ($StateIsCorrect -eq $true) { + $FieldValue = $true + } Else { + $FieldValue = $CurrentState ? $CurrentState : $false + } + Set-CIPPStandardsCompareField -FieldName 'standards.PhishingSimulations' -FieldValue $FieldValue -Tenant $Tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 index 8ba28e6582f0..79f52025b76b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 @@ -42,7 +42,7 @@ function Invoke-CIPPStandardQuarantineRequestAlert { if ($StateIsCorrect -eq $true) { Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Quarantine Request Alert is configured correctly' -sev Info } else { - $cmdparams = @{ + $cmdParams = @{ 'NotifyUser' = $Settings.NotifyUser 'Category' = 'ThreatManagement' 'Operation' = 'QuarantineRequestReleaseMessage' @@ -52,8 +52,8 @@ function Invoke-CIPPStandardQuarantineRequestAlert { if ($CurrentState.Name -eq $PolicyName) { try { - $cmdparams['Identity'] = $PolicyName - New-ExoRequest -TenantId $Tenant -cmdlet 'Set-ProtectionAlert' -Compliance -cmdparams $cmdparams -UseSystemMailbox $true + $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 @@ -61,10 +61,10 @@ function Invoke-CIPPStandardQuarantineRequestAlert { } } else { try { - $cmdparams['name'] = $PolicyName - $cmdparams['ThreatType'] = 'Activity' + $cmdParams['name'] = $PolicyName + $cmdParams['ThreatType'] = 'Activity' - New-ExoRequest -TenantId $Tenant -cmdlet 'New-ProtectionAlert' -Compliance -cmdparams $cmdparams -UseSystemMailbox $true + 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 diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 index 6cb255e67378..52d311bbb236 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 @@ -39,7 +39,7 @@ function Invoke-CIPPStandardRotateDKIM { if ($DKIM) { $DKIM | ForEach-Object { try { - (New-ExoRequest -tenantid $tenant -cmdlet 'Rotate-DkimSigningConfig' -cmdparams @{ KeySize = 2048; Identity = $_.Identity } -useSystemMailbox $true) + (New-ExoRequest -tenantid $tenant -cmdlet 'Rotate-DkimSigningConfig' -cmdParams @{ KeySize = 2048; Identity = $_.Identity } -useSystemMailbox $true) Write-LogMessage -API 'Standards' -tenant $tenant -message "Rotated DKIM for $($_.Identity)" -sev Info } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPAzureB2B.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPAzureB2B.ps1 index 0b445c519394..1a338e3bcdc3 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPAzureB2B.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPAzureB2B.ps1 @@ -22,7 +22,7 @@ function Invoke-CIPPStandardSPAzureB2B { POWERSHELLEQUIVALENT Set-SPOTenant -EnableAzureADB2BIntegration \$true RECOMMENDEDBY - "CIS 3.0" + "CIS" 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 30cf54129538..25a644856841 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPEmailAttestation.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPEmailAttestation.ps1 @@ -40,7 +40,7 @@ function Invoke-CIPPStandardSPEmailAttestation { 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 + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint re-authentication with verification code is already restricted.' -Sev Info } else { $Properties = @{ EmailAttestationReAuthDays = [int]$Settings.Days @@ -51,22 +51,22 @@ function Invoke-CIPPStandardSPEmailAttestation { $Response = Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties if ($Response.ErrorInfo.ErrorMessage) { $ErrorMessage = Get-NormalizedError -Message $Response.ErrorInfo.ErrorMessage - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to set reauthentication with verification code restriction. Error: $ErrorMessage" -Sev Error + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to set re-authentication with verification code restriction. Error: $ErrorMessage" -Sev Error } else { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully set reauthentication with verification code restriction.' -Sev Info + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully set re-authentication 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 + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to set re-authentication 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 + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Re-authentication with verification code is restricted.' -Sev Info } else { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Reauthentication with verification code is not restricted.' -Sev Alert + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Re-authentication with verification code is not restricted.' -Sev Alert } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 index 1fbad860859c..aa8f99ab850b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 @@ -23,7 +23,7 @@ function Invoke-CIPPStandardSPExternalUserExpiration { POWERSHELLEQUIVALENT Set-SPOTenant -ExternalUserExpireInDays 30 -ExternalUserExpirationRequired \$True RECOMMENDEDBY - "CIS 3.0" + "CIS" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 index cf2a092f3b9e..7c37a8cc98da 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 @@ -85,7 +85,7 @@ function Invoke-CIPPStandardSafeAttachmentPolicy { if ($StateIsCorrect -eq $true) { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Safe Attachment Policy already correctly configured' -sev Info } else { - $cmdparams = @{ + $cmdParams = @{ Enable = $true Action = $Settings.SafeAttachmentAction QuarantineTag = $Settings.QuarantineTag @@ -95,16 +95,16 @@ function Invoke-CIPPStandardSafeAttachmentPolicy { if ($CurrentState.Name -eq $PolicyName) { try { - $cmdparams.Add('Identity', $PolicyName) - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-SafeAttachmentPolicy' -cmdparams $cmdparams -UseSystemMailbox $true + $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 + $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 $_ @@ -113,27 +113,27 @@ function Invoke-CIPPStandardSafeAttachmentPolicy { } if ($RuleStateIsCorrect -eq $false) { - $cmdparams = @{ + $cmdParams = @{ Priority = 0 RecipientDomainIs = $AcceptedDomains.Name } if ($RuleState.SafeAttachmentPolicy -ne $PolicyName) { - $cmdparams.Add('SafeAttachmentPolicy', $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 + $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 + $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 $_ diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 index 6227806d8895..199d74e38e1c 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 @@ -5,10 +5,10 @@ function Invoke-CIPPStandardSafeLinksPolicy { .COMPONENT (APIName) SafeLinksPolicy .SYNOPSIS - (Label) Default SafeLinks Policy + (Label) Default Safe Links 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 + (Helptext) This creates a Safe Links 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 Safe Links 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 @@ -20,6 +20,7 @@ function Invoke-CIPPStandardSafeLinksPolicy { {"type":"switch","label":"AllowClickThrough","name":"standards.SafeLinksPolicy.AllowClickThrough"} {"type":"switch","label":"DisableUrlRewrite","name":"standards.SafeLinksPolicy.DisableUrlRewrite"} {"type":"switch","label":"EnableOrganizationBranding","name":"standards.SafeLinksPolicy.EnableOrganizationBranding"} + {"type":"autoComplete","multiple":true,"creatable":true,"required":false,"name":"standards.SafeLinksPolicy.DoNotRewriteUrls","label":"Do not rewrite the following URLs in email"} IMPACT Low Impact ADDEDDATE @@ -89,7 +90,7 @@ function Invoke-CIPPStandardSafeLinksPolicy { if ($StateIsCorrect -eq $true) { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'SafeLink Policy already correctly configured' -sev Info } else { - $cmdparams = @{ + $cmdParams = @{ EnableSafeLinksForEmail = $true EnableSafeLinksForTeams = $true EnableSafeLinksForOffice = $true @@ -105,16 +106,16 @@ function Invoke-CIPPStandardSafeLinksPolicy { if ($CurrentState.Name -eq $Policyname) { try { - $cmdparams.Add('Identity', $PolicyName) - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-SafeLinksPolicy' -cmdparams $cmdparams -UseSystemMailbox $true + $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 + $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 $_ @@ -123,27 +124,27 @@ function Invoke-CIPPStandardSafeLinksPolicy { } if ($RuleStateIsCorrect -eq $false) { - $cmdparams = @{ + $cmdParams = @{ Priority = 0 RecipientDomainIs = $AcceptedDomains.Name } if ($RuleState.SafeLinksPolicy -ne $PolicyName) { - $cmdparams.Add('SafeLinksPolicy', $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 + $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 + $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 $_ diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 index 11357cbd81a0..72899c27ce9b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 @@ -15,7 +15,7 @@ function Invoke-CIPPStandardSafeSendersDisable { TAG ADDEDCOMPONENT DISABLEDFEATURES - + {"report":true,"warn":true,"remediate":false} IMPACT Medium Impact ADDEDDATE diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSharePointMassDeletionAlert.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSharePointMassDeletionAlert.ps1 new file mode 100644 index 000000000000..08404d523264 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSharePointMassDeletionAlert.ps1 @@ -0,0 +1,109 @@ +function Invoke-CIPPStandardSharePointMassDeletionAlert { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) SharePointMassDeletionAlert + .SYNOPSIS + (Label) SharePoint Mass Deletion Alert + .DESCRIPTION + (Helptext) Sets a e-mail address to alert when a User deletes more than 20 SharePoint files within 60 minutes. NB: Requires a Office 365 E5 subscription, Office 365 E3 with Threat Intelligence or Office 365 EquivioAnalytics add-on. + (DocsDescription) Sets a e-mail address to alert when a User deletes more than 20 SharePoint files within 60 minutes. This is useful for monitoring and ensuring that the correct SharePoint files are deleted. NB: Requires a Office 365 E5 subscription, Office 365 E3 with Threat Intelligence or Office 365 EquivioAnalytics add-on. + .NOTES + CAT + Defender Standards + TAG + ADDEDCOMPONENT + {"type":"number","name":"standards.SharePointMassDeletionAlert.Threshold","label":"Max files to delete within the time frame","defaultValue":20} + {"type":"number","name":"standards.SharePointMassDeletionAlert.TimeWindow","label":"Time frame in minutes","defaultValue":60} + {"type":"autoComplete","multiple":true,"creatable":true,"required":true,"name":"standards.SharePointMassDeletionAlert.NotifyUser","label":"E-mail to receive the alert"} + IMPACT + Low Impact + ADDEDDATE + 2025-04-07 + 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) + + $PolicyName = 'CIPP SharePoint mass deletion of files by a user' + + $CurrentState = New-ExoRequest -TenantId $Tenant -cmdlet 'Get-ProtectionAlert' -Compliance | + Where-Object { $_.Name -eq $PolicyName } | + Select-Object -Property * + + $EmailsOutsideSettings = $CurrentState.NotifyUser | Where-Object { $_ -notin $Settings.NotifyUser.value } + $MissingEmailsInSettings = $Settings.NotifyUser.value | Where-Object { $_ -notin $CurrentState.NotifyUser } + + $StateIsCorrect = ($EmailsOutsideSettings.Count -eq 0) -and + ($MissingEmailsInSettings.Count -eq 0) -and + ($CurrentState.Threshold -eq $Settings.Threshold) -and + ($CurrentState.TimeWindow -eq $Settings.TimeWindow) + + If ($Settings.remediate -eq $true) { + If ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint mass deletion of files alert is configured correctly' -sev Info + } Else { + $cmdParams = @{ + 'NotifyUser' = $Settings.NotifyUser.value + 'Category' = 'DataGovernance' + 'Operation' = 'FileDeleted' + 'Severity' = 'High' + 'AggregationType' = '1' + 'Threshold' = $Settings.Threshold + 'TimeWindow' = $Settings.TimeWindow + } + + 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 SharePoint mass deletion of files alert' -sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to configure SharePoint mass deletion of files 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 SharePoint mass deletion of files alert' -sev Info + } catch { + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to create SharePoint mass deletion of files alert. Error: $ErrorMessage" -sev Error + } + } + } + } + + If ($Settings.alert -eq $true) { + If ($StateIsCorrect -eq $true) { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint mass deletion of files alert is enabled' -sev Info + } Else { + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint mass deletion of files alert is disabled' -sev Info + } + } + + If ($Settings.report -eq $true) { + If ($StateIsCorrect -eq $true) { + $Table = $true + } Else { + $Table = [PSCustomObject]@{ + Threshold = $CurrentState.Threshold + TimeWindow = $CurrentState.TimeWindow + NotifyUser = $CurrentState.NotifyUser + } + } + + Set-CIPPStandardsCompareField -FieldName 'standards.SharePointMassDeletionAlert' -FieldValue $Table -TenantFilter $Tenant + Add-CIPPBPAField -FieldName 'SharePointMassDeletionAlert' -FieldValue [bool]$StateIsCorrect -StoreAs bool -Tenant $Tenant + } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 index 0665c50176d6..c21bf3472820 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 @@ -24,6 +24,19 @@ function Invoke-CIPPStandardSpamFilterPolicy { {"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"}]} + {"type":"switch","name":"standards.SpamFilterPolicy.IncreaseScoreWithImageLinks","label":"Increase score if message contains image links to remote websites","defaultValue":false} + {"type":"switch","name":"standards.SpamFilterPolicy.IncreaseScoreWithBizOrInfoUrls","label":"Increase score if message contains links to .biz or .info domains","defaultValue":false} + {"type":"switch","name":"standards.SpamFilterPolicy.MarkAsSpamFramesInHtml","label":"Mark as spam if message contains HTML or iframe tags","defaultValue":false} + {"type":"switch","name":"standards.SpamFilterPolicy.MarkAsSpamObjectTagsInHtml","label":"Mark as spam if message contains HTML object tags","defaultValue":false} + {"type":"switch","name":"standards.SpamFilterPolicy.MarkAsSpamEmbedTagsInHtml","label":"Mark as spam if message contains HTML embed tags","defaultValue":false} + {"type":"switch","name":"standards.SpamFilterPolicy.MarkAsSpamFormTagsInHtml","label":"Mark as spam if message contains HTML form tags","defaultValue":false} + {"type":"switch","name":"standards.SpamFilterPolicy.MarkAsSpamWebBugsInHtml","label":"Mark as spam if message contains web bugs (also known as web beacons)","defaultValue":false} + {"type":"switch","name":"standards.SpamFilterPolicy.MarkAsSpamSensitiveWordList","label":"Mark as spam if message contains words from the sensitive words list","defaultValue":false} + {"type":"switch","name":"standards.SpamFilterPolicy.EnableLanguageBlockList","label":"Enable language block list","defaultValue":false} + {"type":"autoComplete","multiple":true,"creatable":true,"required":false,"name":"standards.SpamFilterPolicy.LanguageBlockList","label":"Languages to block (uppercase ISO 639-1 two-letter)"} + {"type":"switch","name":"standards.SpamFilterPolicy.EnableRegionBlockList","label":"Enable region block list","defaultValue":false} + {"type":"autoComplete","multiple":true,"creatable":true,"required":false,"name":"standards.SpamFilterPolicy.RegionBlockList","label":"Regions to block (uppercase ISO 3166-1 two-letter)"} + {"type":"autoComplete","multiple":true,"creatable":true,"required":false,"name":"standards.SpamFilterPolicy.AllowedSenderDomains","label":"Allowed sender domains"} IMPACT Medium Impact ADDEDDATE @@ -115,7 +128,7 @@ function Invoke-CIPPStandardSpamFilterPolicy { if ($StateIsCorrect -eq $true) { Write-LogMessage -API 'Standards' -Tenant $Tenant -message 'Spam Filter Policy already correctly configured' -sev Info } else { - $cmdparams = @{ + $cmdParams = @{ SpamAction = $SpamAction SpamQuarantineTag = $SpamQuarantineTag HighConfidenceSpamAction = $HighConfidenceSpamAction diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 index 19b0d7626b04..8a843339b622 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 @@ -16,6 +16,7 @@ function Invoke-CIPPStandardSpoofWarn { "CIS" ADDEDCOMPONENT {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.SpoofWarn.state","options":[{"label":"Enabled","value":"enabled"},{"label":"Disabled","value":"disabled"}]} + {"type":"autoComplete","multiple":true,"creatable":true,"required":false,"label":"Enter allowed senders(domain.com, *.domain.com or test@domain.com)","name":"standards.SpoofWarn.AllowListAdd"} IMPACT Low Impact ADDEDDATE diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 index 57946ee6bccd..148144a0da29 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 @@ -15,9 +15,9 @@ function Invoke-CIPPStandardStaleEntraDevices { TAG "CIS" ADDEDCOMPONENT - {"type":"number","name":"standards.StaleEntraDevices.deviceAgeThreshold","label":"Days before stale(Dont set below 30)"} + {"type":"number","name":"standards.StaleEntraDevices.deviceAgeThreshold","label":"Days before stale(Do not set below 30)"} DISABLEDFEATURES - + {"report":false,"warn":false,"remediate":true} IMPACT High Impact ADDEDDATE @@ -47,7 +47,7 @@ function Invoke-CIPPStandardStaleEntraDevices { # Properties to look at: # approximateLastSignInDateTime: For knowing when the device last signed in # enrollmentProfileName and operatingSystem: For knowing if it's an AutoPilot device - # managementType or isManaged: For knowing if it's an Intune managed device. If it is, should be removed from Intune also. Stale intune standard could prossibly be used for this. + # managementType or isManaged: For knowing if it's an Intune managed device. If it is, should be removed from Intune also. Stale intune standard could possibly be used for this. # profileType: For knowing if it's only registered or also managed # accountEnabled: For knowing if the device is disabled or not diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEmailIntegration.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEmailIntegration.ps1 index c6cdaa239035..7e33ceca0f9c 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEmailIntegration.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEmailIntegration.ps1 @@ -22,7 +22,7 @@ Function Invoke-CIPPStandardTeamsEmailIntegration { POWERSHELLEQUIVALENT Set-CsTeamsClientConfiguration -AllowEmailIntoChannel \$false RECOMMENDEDBY - "CIS 3.0" + "CIS" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK @@ -42,13 +42,13 @@ Function Invoke-CIPPStandardTeamsEmailIntegration { if ($StateIsCorrect -eq $true) { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams Email Integration settings already set.' -sev Info } else { - $cmdparams = @{ + $cmdParams = @{ Identity = 'Global' AllowEmailIntoChannel = $Settings.AllowEmailIntoChannel } try { - New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTeamsClientConfiguration' -CmdParams $cmdparams + 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 diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalAccessPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalAccessPolicy.ps1 index 544f7ca8e921..6fccb1a51fa1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalAccessPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalAccessPolicy.ps1 @@ -47,7 +47,7 @@ function Invoke-CIPPStandardTeamsExternalAccessPolicy { if ($StateIsCorrect -eq $true) { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'External Access Policy already set.' -sev Info } else { - $cmdparams = @{ + $cmdParams = @{ Identity = 'Global' EnableFederationAccess = $Settings.EnableFederationAccess EnablePublicCloudAccess = $Settings.EnablePublicCloudAccess @@ -55,7 +55,7 @@ function Invoke-CIPPStandardTeamsExternalAccessPolicy { } try { - New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsExternalAccessPolicy' -CmdParams $cmdparams + 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 diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalFileSharing.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalFileSharing.ps1 index 7c0da8594146..0923d4e6206b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalFileSharing.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalFileSharing.ps1 @@ -26,7 +26,7 @@ function Invoke-CIPPStandardTeamsExternalFileSharing { POWERSHELLEQUIVALENT Set-CsTeamsClientConfiguration -AllowGoogleDrive \$false -AllowShareFile \$false -AllowBox \$false -AllowDropBox \$false -AllowEgnyte \$false RECOMMENDEDBY - "CIS 3.0" + "CIS" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK @@ -54,7 +54,7 @@ function Invoke-CIPPStandardTeamsExternalFileSharing { if ($StateIsCorrect -eq $true) { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Teams External File Sharing already set.' -sev Info } else { - $cmdparams = @{ + $cmdParams = @{ AllowGoogleDrive = $Settings.AllowGoogleDrive AllowShareFile = $Settings.AllowShareFile AllowBox = $Settings.AllowBox @@ -63,7 +63,7 @@ function Invoke-CIPPStandardTeamsExternalFileSharing { } try { - New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTeamsClientConfiguration' -CmdParams $cmdparams + 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 diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 index 252758450c57..e339a02fd911 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 @@ -96,7 +96,7 @@ function Invoke-CIPPStandardTeamsFederationConfiguration { if ($StateIsCorrect -eq $true) { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Federation Configuration already set.' -sev Info } else { - $cmdparams = @{ + $cmdParams = @{ Identity = 'Global' AllowTeamsConsumer = $Settings.AllowTeamsConsumer AllowPublicUsers = $Settings.AllowPublicUsers @@ -105,13 +105,13 @@ function Invoke-CIPPStandardTeamsFederationConfiguration { } if (!$AllowedDomainsAsAList) { - $cmdparams.AllowedDomains = $AllowedDomains + $cmdParams.AllowedDomains = $AllowedDomains } else { - $cmdparams.AllowedDomainsAsAList = $AllowedDomainsAsAList + $cmdParams.AllowedDomainsAsAList = $AllowedDomainsAsAList } try { - New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTenantFederationConfiguration' -CmdParams $cmdparams + 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 diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 index c74e89c8d606..5b37cbf775dd 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 @@ -25,7 +25,7 @@ function Invoke-CIPPStandardTeamsGlobalMeetingPolicy { POWERSHELLEQUIVALENT Set-CsTeamsMeetingPolicy -AllowAnonymousUsersToJoinMeeting \$false -AllowAnonymousUsersToStartMeeting \$false -AutoAdmittedUsers EveryoneInCompanyExcludingGuests -AllowPSTNUsersToBypassLobby \$false -MeetingChatEnabledType EnabledExceptAnonymous -DesignatedPresenterRoleMode \$DesignatedPresenterRoleMode -AllowExternalParticipantGiveRequestControl \$false RECOMMENDEDBY - "CIS 3.0" + "CIS" UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 index a70ad82d78a6..59fe213f54a0 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 @@ -14,7 +14,7 @@ function Invoke-CIPPStandardTeamsMeetingsByDefault { Exchange Standards TAG ADDEDCOMPONENT - {"type":"autoComplete","multiple":false,"label":"Select value","name":"standards.TeamsMeetingsByDefault.state","options":[{"label":"Enabled","value":"true"},{"label":"Disabled","value":"false"}]} + {"type":"autoComplete","multiple":false,"creatable":false,"label":"Select value","name":"standards.TeamsMeetingsByDefault.state","options":[{"label":"Enabled","value":"true"},{"label":"Disabled","value":"false"}]} IMPACT Low Impact ADDEDDATE diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 index 501dbaba13a0..6de85ba0ad64 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 @@ -65,7 +65,7 @@ Function Invoke-CIPPStandardTeamsMessagingPolicy { if ($StateIsCorrect -eq $true) { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'Global Teams Messaging policy already configured.' -sev Info } else { - $cmdparams = @{ + $cmdParams = @{ Identity = 'Global' AllowOwnerDeleteMessage = $Settings.AllowOwnerDeleteMessage AllowUserDeleteMessage = $Settings.AllowUserDeleteMessage @@ -79,7 +79,7 @@ Function Invoke-CIPPStandardTeamsMessagingPolicy { } try { - New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Set-CsTeamsMessagingPolicy' -CmdParams $cmdparams + 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 diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 index d7dd378a2562..1289d1682296 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 - + {"report":true,"warn":true,"remediate":false} IMPACT Medium Impact ADDEDDATE @@ -51,10 +51,10 @@ function Invoke-CIPPStandardTransportRuleTemplate { Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully created transport rule for $tenant" -sev 'Info' } - Write-LogMessage -API $APINAME -tenant $Tenant -message "Created transport rule for $($tenantfilter)" -sev 'Debug' + Write-LogMessage -API $APINAME -tenant $Tenant -message "Created transport rule for $($tenantFilter)" -sev 'Debug' } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Could not create transport rule for $($tenantfilter): $ErrorMessage" -sev 'Error' + Write-LogMessage -API 'Standards' -tenant $tenant -message "Could not create transport rule for $($tenantFilter): $ErrorMessage" -sev 'Error' } } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserPreferredLanguage.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserPreferredLanguage.ps1 index 0907d6c5f485..0bbc6e4372b7 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserPreferredLanguage.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserPreferredLanguage.ps1 @@ -37,7 +37,7 @@ function Invoke-CIPPStandardUserPreferredLanguage { if (($IncorrectUsers | Measure-Object).Count -gt 0) { try { foreach ($user in $IncorrectUsers) { - $cmdparams = @{ + $cmdParams = @{ tenantid = $Tenant uri = "https://graph.microsoft.com/beta/users/$($user.userPrincipalName)" AsApp = $true @@ -47,7 +47,7 @@ function Invoke-CIPPStandardUserPreferredLanguage { } | ConvertTo-Json ContentType = 'application/json; charset=utf-8' } - $null = New-GraphPOSTRequest @cmdparams + $null = New-GraphPOSTRequest @cmdParams Write-LogMessage -API 'Standards' -tenant $Tenant -message "Preferred language for $($user.userPrincipalName) has been set to $preferredLanguage" -sev Info } } catch { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 index ed84d3466ba5..97534b7ac800 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 @@ -14,7 +14,7 @@ function Invoke-CIPPStandardcalDefault { Exchange Standards TAG DISABLEDFEATURES - + {"report":true,"warn":true,"remediate":false} ADDEDCOMPONENT {"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 @@ -33,12 +33,12 @@ function Invoke-CIPPStandardcalDefault { param($Tenant, $Settings, $QueueItem) ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'calDefault' - # Get permissionlevel value using null-coalescing operator + # Get permissionLevel value using null-coalescing operator $permissionLevel = $Settings.permissionLevel.value ?? $Settings.permissionLevel # Input validation if ([string]::IsNullOrWhiteSpace($permissionLevel) -or $permissionLevel -eq 'Select a value') { - Write-LogMessage -API 'Standards' -tenant $tenant -message 'calDefault: Invalid permissionlevel parameter set' -sev Error + Write-LogMessage -API 'Standards' -tenant $tenant -message 'calDefault: Invalid permissionLevel parameter set' -sev Error Return } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneBrandingProfile.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneBrandingProfile.ps1 index ce778dcefd70..b7aaa6277e06 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneBrandingProfile.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneBrandingProfile.ps1 @@ -69,7 +69,7 @@ function Invoke-CIPPStandardintuneBrandingProfile { if ($Settings.onlineSupportSiteUrl) { $Body.onlineSupportSiteUrl = $Settings.onlineSupportSiteUrl } if ($Settings.privacyUrl) { $Body.privacyUrl = $Settings.privacyUrl } - $cmdparams = @{ + $cmdParams = @{ tenantid = $tenant uri = 'https://graph.microsoft.com/beta/deviceManagement/intuneBrandingProfiles/c3a59481-1bf2-46ce-94b3-66eec07a8d60' AsApp = $true @@ -79,7 +79,7 @@ function Invoke-CIPPStandardintuneBrandingProfile { } try { - New-GraphPostRequest @cmdparams + New-GraphPostRequest @cmdParams Write-LogMessage -API 'Standards' -tenant $tenant -message 'Successfully updated Intune Branding Profile' -sev Info } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 index fa622a54961d..cbe8ef576aa1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 @@ -41,7 +41,7 @@ function Invoke-CIPPStandardintuneDeviceReg { } else { try { $PreviousSetting.userDeviceQuota = $Settings.max - $Newbody = ConvertTo-Json -Compress -InputObject $PreviousSetting -Depth 5 + $NewBody = ConvertTo-Json -Compress -InputObject $PreviousSetting -Depth 5 $null = New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/deviceRegistrationPolicy' -Type PUT -Body $NewBody -ContentType 'application/json' Write-LogMessage -API 'Standards' -tenant $tenant -message "Set user device quota to $($Settings.max)" -sev Info } catch { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 index 8aa0b7f75e74..e6a7f929a4c8 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 @@ -5,7 +5,7 @@ function Invoke-CIPPStandardintuneRequireMFA { .COMPONENT (APIName) intuneRequireMFA .SYNOPSIS - (Label) Require Multifactor Authentication to register or join devices with Microsoft Entra + (Label) Require Multi-factor Authentication to register or join devices with Microsoft Entra .DESCRIPTION (Helptext) Requires MFA for all users to register devices with Intune. This is useful when not using Conditional Access. (DocsDescription) Requires MFA for all users to register devices with Intune. This is useful when not using Conditional Access. @@ -38,7 +38,7 @@ function Invoke-CIPPStandardintuneRequireMFA { try { $NewSetting = $PreviousSetting $NewSetting.multiFactorAuthConfiguration = 'required' - $Newbody = ConvertTo-Json -Compress -InputObject $NewSetting -Depth 10 + $NewBody = ConvertTo-Json -Compress -InputObject $NewSetting -Depth 10 New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/deviceRegistrationPolicy' -Type PUT -Body $NewBody -ContentType 'application/json' Write-LogMessage -API 'Standards' -tenant $tenant -message 'Set required to use MFA when joining/registering Entra Devices' -sev Info } catch { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardlaps.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardlaps.ps1 index 54ba250fe97a..dde78c661881 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardlaps.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardlaps.ps1 @@ -36,7 +36,7 @@ function Invoke-CIPPStandardlaps { If ($Settings.remediate -eq $true) { try { $PreviousSetting.localAdminPassword.isEnabled = $true - $Newbody = ConvertTo-Json -Compress -InputObject $PreviousSetting -Depth 10 + $NewBody = ConvertTo-Json -Compress -InputObject $PreviousSetting -Depth 10 New-GraphPostRequest -tenantid $Tenant -Uri 'https://graph.microsoft.com/beta/policies/deviceRegistrationPolicy' -Type PUT -Body $NewBody -ContentType 'application/json' Write-LogMessage -API 'Standards' -tenant $Tenant -message 'LAPS has been enabled.' -sev Info } catch { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 index 4dc839781766..60f6fe4d9ea4 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 @@ -70,13 +70,18 @@ function Invoke-CIPPStandardsharingCapability { } if ($Settings.alert -eq $true) { - if ($CurrentInfo.sharingCapability -eq $level) { Write-LogMessage -API 'Standards' -tenant $Tenant -message "Sharing level is set to $level" -sev Info - $FieldValue = $true } else { Write-StandardsAlert -message "Sharing level is not set to $level" -object $CurrentInfo -tenant $Tenant -standardName 'sharingCapability' -standardId $Settings.standardId Write-LogMessage -API 'Standards' -tenant $Tenant -message "Sharing level is not set to $level" -sev Info + } + } + + if ($Settings.report -eq $true) { + if ($CurrentInfo.sharingCapability -eq $level) { + $FieldValue = $true + } else { $FieldValue = $CurrentInfo | Select-Object -Property sharingCapability } Set-CIPPStandardsCompareField -FieldName 'standards.sharingCapability' -FieldValue $FieldValue -Tenant $Tenant diff --git a/Modules/CIPPCore/Public/Test-CIPPAccessPermissions.ps1 b/Modules/CIPPCore/Public/Test-CIPPAccessPermissions.ps1 index a688a09160df..8aab1f89a830 100644 --- a/Modules/CIPPCore/Public/Test-CIPPAccessPermissions.ps1 +++ b/Modules/CIPPCore/Public/Test-CIPPAccessPermissions.ps1 @@ -35,12 +35,12 @@ function Test-CIPPAccessPermissions { try { Disable-AzContextAutosave -Scope Process | Out-Null $null = Connect-AzAccount -Identity - $SubscriptionId = $ENV:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 + $SubscriptionId = $env:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 $null = Set-AzContext -SubscriptionId $SubscriptionId - $KV = $ENV:WEBSITE_DEPLOYMENT_ID + $KV = $env:WEBSITE_DEPLOYMENT_ID $KeyVaultRefresh = Get-AzKeyVaultSecret -VaultName $kv -Name 'RefreshToken' -AsPlainText - if ($ENV:RefreshToken -ne $KeyVaultRefresh) { + if ($env:RefreshToken -ne $KeyVaultRefresh) { $Success = $false $ErrorMessages.Add('Your refresh token does not match key vault, wait 30 minutes for the function app to update.') | Out-Null } else { diff --git a/Modules/CIPPCore/Public/Test-CIPPAccessTenant.ps1 b/Modules/CIPPCore/Public/Test-CIPPAccessTenant.ps1 index 1779f526d694..a54a22d5cc2e 100644 --- a/Modules/CIPPCore/Public/Test-CIPPAccessTenant.ps1 +++ b/Modules/CIPPCore/Public/Test-CIPPAccessTenant.ps1 @@ -75,7 +75,7 @@ function Test-CIPPAccessTenant { foreach ($RoleId in $ExpectedRoles) { $GraphRole = $GDAPRolesGraph.body.value | Where-Object -Property roleDefinitionId -EQ $RoleId.Id - $Role = $GraphRole.principal | Where-Object -Property organizationId -EQ $ENV:TenantID + $Role = $GraphRole.principal | Where-Object -Property organizationId -EQ $env:TenantID if (!$Role) { $MissingRoles.Add( diff --git a/Modules/CIPPCore/Public/Test-CIPPGDAPRelationships.ps1 b/Modules/CIPPCore/Public/Test-CIPPGDAPRelationships.ps1 index 80af8e6b09ef..b9b16bbc0db6 100644 --- a/Modules/CIPPCore/Public/Test-CIPPGDAPRelationships.ps1 +++ b/Modules/CIPPCore/Public/Test-CIPPGDAPRelationships.ps1 @@ -10,7 +10,7 @@ function Test-CIPPGDAPRelationships { $MissingGroups = [System.Collections.Generic.List[object]]@() try { #Get graph request to list all relationships. - $Relationships = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships?`$filter=status eq 'active'" -tenantid $ENV:TenantID -NoAuthCheck $true + $Relationships = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/tenantRelationships/delegatedAdminRelationships?`$filter=status eq 'active'" -tenantid $env:TenantID -NoAuthCheck $true #Group relationships by tenant. The tenant information is in $relationships.customer.TenantId. $RelationshipsByTenant = $Relationships | Group-Object -Property { $_.customer.TenantId } foreach ($Tenant in $RelationshipsByTenant) { diff --git a/Modules/CIPPCore/Public/Tools/Import-CommunityTemplate.ps1 b/Modules/CIPPCore/Public/Tools/Import-CommunityTemplate.ps1 index 5cfdcd6b5827..2d3686a1702d 100644 --- a/Modules/CIPPCore/Public/Tools/Import-CommunityTemplate.ps1 +++ b/Modules/CIPPCore/Public/Tools/Import-CommunityTemplate.ps1 @@ -13,97 +13,130 @@ function Import-CommunityTemplate { $Table = Get-CippTable -TableName 'templates' + try { + if ($Template.RowKey) { + Write-Host "This is going to be a direct write to table, it's a CIPP template. We're writing $($Template.RowKey)" + $Template = $Template | Select-Object * -ExcludeProperty Timestamp - if ($Template.RowKey) { - Write-Host "This is going to be a direct write to table, it's a CIPP template. We're writing $($Template.RowKey)" - $Template = $Template | Select-Object * -ExcludeProperty timestamp - Add-CIPPAzDataTableEntity @Table -Entity $Template -Force - } else { - if ($Template.mailNickname) { $Type = 'Group' } - if ($Template.'@odata.type' -like '*conditionalAccessPolicy*') { $Type = 'ConditionalAccessPolicy' } - Write-Host "The type is $Type" - switch -Wildcard ($Type) { + # Support both objects and json string in repo (support pretty printed json in repo) + if (Test-Json $Template.JSON -ErrorAction SilentlyContinue) { + $NewJSON = $Template.JSON | ConvertFrom-Json + } else { + $NewJSON = $Template.JSON + } + + # Check for existing object + $Existing = Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq '$($Template.RowKey)' and PartitionKey eq '$($Template.PartitionKey)'" -ErrorAction SilentlyContinue - '*Group*' { - $RawJsonObj = [PSCustomObject]@{ - Displayname = $Template.displayName - Description = $Template.Description - MembershipRules = $Template.membershipRule - username = $Template.mailNickname - GUID = $Template.id - groupType = 'generic' - } | ConvertTo-Json -Depth 100 - $entity = @{ - JSON = "$RawJsonObj" - PartitionKey = 'GroupTemplate' - SHA = $SHA - GUID = $Template.id - RowKey = $Template.id + if ($Existing) { + if ($Existing.PartitionKey -eq 'StandardsTemplateV2') { + # Convert existing JSON to object for updates + if (Test-Json $Existing.JSON -ErrorAction SilentlyContinue) { + $ExistingJSON = $Existing.JSON | ConvertFrom-Json + } else { + $ExistingJSON = $Existing.JSON + } + # Extract existing tenantFilter and excludedTenants + $tenantFilter = $ExistingJSON.tenantFilter + $excludedTenants = $ExistingJSON.excludedTenants + $NewJSON.tenantFilter = $tenantFilter + $NewJSON.excludedTenants = $excludedTenants } - Add-CIPPAzDataTableEntity @Table -Entity $entity -Force - break } - '*conditionalAccessPolicy*' { - Write-Host $MigrationTable - $Template = ([pscustomobject]$Template) | ForEach-Object { - $NonEmptyProperties = $_.psobject.Properties | Where-Object { $null -ne $_.Value } | Select-Object -ExpandProperty Name - $_ | Select-Object -Property $NonEmptyProperties - } - $id = $Template.id - $Template = $Template | Select-Object * -ExcludeProperty lastModifiedDateTime, 'assignments', '#microsoft*', '*@odata.navigationLink', '*@odata.associationLink', '*@odata.context', 'ScopeTagIds', 'supportsScopeTags', 'createdDateTime', '@odata.id', '@odata.editLink', '*odata.type', 'roleScopeTagIds@odata.type', createdDateTime, 'createdDateTime@odata.type' - Remove-ODataProperties -Object $Template - $RawJson = ConvertTo-Json -InputObject $Template -Depth 100 -Compress - #Replace the ids with the displayname by using the migration table, this is a simple find and replace each instance in the JSON. - $MigrationTable.objects | ForEach-Object { - if ($RawJson -match $_.ID) { - $RawJson = $RawJson.Replace($_.ID, $($_.DisplayName)) + # Re-compress JSON and save to table + $NewJSON = [string]($NewJSON | ConvertTo-Json -Depth 100 -Compress) + $Template.JSON = $NewJSON + $Template | Add-Member -MemberType NoteProperty -Name SHA -Value $SHA -Force + Add-CIPPAzDataTableEntity @Table -Entity $Template -Force + } else { + if ($Template.mailNickname) { $Type = 'Group' } + if ($Template.'@odata.type' -like '*conditionalAccessPolicy*') { $Type = 'ConditionalAccessPolicy' } + Write-Host "The type is $Type" + switch -Wildcard ($Type) { + + '*Group*' { + $RawJsonObj = [PSCustomObject]@{ + Displayname = $Template.displayName + Description = $Template.Description + MembershipRules = $Template.membershipRule + username = $Template.mailNickname + GUID = $Template.id + groupType = 'generic' + } | ConvertTo-Json -Depth 100 + $entity = @{ + JSON = "$RawJsonObj" + PartitionKey = 'GroupTemplate' + SHA = $SHA + GUID = $Template.id + RowKey = $Template.id } + Add-CIPPAzDataTableEntity @Table -Entity $entity -Force + break } - $entity = @{ - JSON = "$RawJson" - PartitionKey = 'CATemplate' - SHA = $SHA - GUID = $ID - RowKey = $ID - } - Add-CIPPAzDataTableEntity @Table -Entity $entity -Force - break - } - default { - $URLName = switch -Wildcard ($Template.'@odata.id') { - '*CompliancePolicies*' { 'DeviceCompliancePolicies' } - '*deviceConfigurations*' { 'Device' } - '*DriverUpdateProfiles*' { 'windowsDriverUpdateProfiles' } - '*SettingsCatalog*' { 'Catalog' } - '*configurationPolicies*' { 'Catalog' } - '*managedAppPolicies*' { 'AppProtection' } - '*deviceAppManagement*' { 'AppProtection' } + '*conditionalAccessPolicy*' { + Write-Host $MigrationTable + $Template = ([pscustomobject]$Template) | ForEach-Object { + $NonEmptyProperties = $_.psobject.Properties | Where-Object { $null -ne $_.Value } | Select-Object -ExpandProperty Name + $_ | Select-Object -Property $NonEmptyProperties + } + $id = $Template.id + $Template = $Template | Select-Object * -ExcludeProperty lastModifiedDateTime, 'assignments', '#microsoft*', '*@odata.navigationLink', '*@odata.associationLink', '*@odata.context', 'ScopeTagIds', 'supportsScopeTags', 'createdDateTime', '@odata.id', '@odata.editLink', '*odata.type', 'roleScopeTagIds@odata.type', createdDateTime, 'createdDateTime@odata.type' + Remove-ODataProperties -Object $Template + $RawJson = ConvertTo-Json -InputObject $Template -Depth 100 -Compress + #Replace the ids with the displayname by using the migration table, this is a simple find and replace each instance in the JSON. + $MigrationTable.objects | ForEach-Object { + if ($RawJson -match $_.ID) { + $RawJson = $RawJson.Replace($_.ID, $($_.DisplayName)) + } + } + $entity = @{ + JSON = "$RawJson" + PartitionKey = 'CATemplate' + SHA = $SHA + GUID = $ID + RowKey = $ID + } + Add-CIPPAzDataTableEntity @Table -Entity $entity -Force + break } - $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' - Remove-ODataProperties -Object $RawJson - $RawJson = $RawJson | ConvertTo-Json -Depth 100 -Compress + default { + $URLName = switch -Wildcard ($Template.'@odata.id') { + '*CompliancePolicies*' { 'DeviceCompliancePolicies' } + '*deviceConfigurations*' { 'Device' } + '*DriverUpdateProfiles*' { 'windowsDriverUpdateProfiles' } + '*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' + Remove-ODataProperties -Object $RawJson + $RawJson = $RawJson | ConvertTo-Json -Depth 100 -Compress - #create a new template - $RawJsonObj = [PSCustomObject]@{ - Displayname = $Template.displayName ?? $template.Name - Description = $Template.Description - RAWJson = $RawJson - Type = $URLName - GUID = $ID - } | ConvertTo-Json -Depth 100 -Compress + #create a new template + $RawJsonObj = [PSCustomObject]@{ + Displayname = $Template.displayName ?? $template.Name + Description = $Template.Description + RAWJson = $RawJson + Type = $URLName + GUID = $ID + } | ConvertTo-Json -Depth 100 -Compress - $entity = @{ - JSON = "$RawJsonObj" - PartitionKey = 'IntuneTemplate' - SHA = $SHA - GUID = $ID - RowKey = $ID - } - Add-CIPPAzDataTableEntity @Table -Entity $entity -Force + $entity = @{ + JSON = "$RawJsonObj" + PartitionKey = 'IntuneTemplate' + SHA = $SHA + GUID = $ID + RowKey = $ID + } + Add-CIPPAzDataTableEntity @Table -Entity $entity -Force + } } } + } catch { + Write-Warning "Community template import failed. Error: $($_.Exception.Message)" + Write-Information $_.InvocationInfo.PositionMessage } - } diff --git a/Modules/CIPPCore/Public/Webhooks/Invoke-RemoveWebhookAlert.ps1 b/Modules/CIPPCore/Public/Webhooks/Invoke-RemoveWebhookAlert.ps1 index 9c56fd9dcbaf..f4462cb8217a 100644 --- a/Modules/CIPPCore/Public/Webhooks/Invoke-RemoveWebhookAlert.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/Invoke-RemoveWebhookAlert.ps1 @@ -11,7 +11,8 @@ Function Invoke-RemoveWebhookAlert { 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 { $WebhookTable = Get-CIPPTable -TableName 'SchedulerConfig' diff --git a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 index ab8dc85a36c2..6824b08058ea 100644 --- a/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1 @@ -41,6 +41,9 @@ function Test-CIPPAuditLogRules { } } + Write-Warning '## Audit Log Configuration ##' + Write-Information ($Configuration | ConvertTo-Json -Depth 10) + try { $LogCount = $Rows.count $RunGuid = (New-Guid).Guid @@ -98,18 +101,19 @@ function Test-CIPPAuditLogRules { $HasLocationData = $false if (![string]::IsNullOrEmpty($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 - } + + $IPRegex = '^(?(?:\d{1,3}(?:\.\d{1,3}){3}|\[[0-9a-fA-F:]+\]|[0-9a-fA-F:]+))(?::\d+)?$' + $Data.clientip = $Data.clientip -replace $IPRegex, '$1' -replace '[\[\]]', '' + # Check if IP is on trusted IP list - $TrustedIP = Get-CIPPAzDataTableEntity @TrustedIPTable -Filter "((PartitionKey eq '$TenantFilter') or (PartitionKey eq 'AllTenants')) and RowKey eq '$($Data.clientip)' and state eq 'Trusted'" + $TrustedIP = Get-CIPPAzDataTableEntity @TrustedIPTable -Filter "((PartitionKey eq '$TenantFilter') or (PartitionKey eq 'AllTenants')) and RowKey eq '$($Data.clientip)' and state eq 'Trusted'" if ($TrustedIP) { #write-warning "IP $($Data.clientip) is trusted" $Trusted = $true } if (!$Trusted) { $CacheLookupStartTime = Get-Date - $Location = Get-CIPPAzDataTableEntity @LocationTable -Filter "RowKey eq '$($Data.clientIp)'" | Select-Object -Last 1 -ExcludeProperty Tenant + $Location = Get-AzDataTableEntity @LocationTable -Filter "PartitionKey eq 'ip' and RowKey eq '$($Data.clientIp)'" | Select-Object -ExcludeProperty Tenant $CacheLookupEndTime = Get-Date $CacheLookupSeconds = ($CacheLookupEndTime - $CacheLookupStartTime).TotalSeconds Write-Warning "Cache lookup for IP $($Data.clientip) took $CacheLookupSeconds seconds" @@ -185,39 +189,45 @@ function Test-CIPPAuditLogRules { #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)" - $Where = $Configuration | ForEach-Object { - if ($TenantFilter -in $_.Excluded.value) { - return - } - $conditions = $_.Conditions | ConvertFrom-Json | Where-Object { $_.Input.value -ne '' } - $actions = $_.Actions - $conditionStrings = [System.Collections.Generic.List[string]]::new() - $CIPPClause = [System.Collections.Generic.List[string]]::new() - $AddedLocationCondition = $false - foreach ($condition in $conditions) { - if ($condition.Property.label -eq 'CIPPGeoLocation' -and !$AddedLocationCondition) { - $conditionsString.Add("`$_.HasLocationData -eq `$true") - $CIPPClause.Add('HasLocationData is true') - $AddedLocationCondition = $true + try { + $Where = foreach ($Config in $Configuration) { + if ($TenantFilter -in $Config.Excluded.value) { + continue } - $value = if ($condition.Input.value -is [array]) { - $arrayAsString = $condition.Input.value | ForEach-Object { - "'$_'" + $conditions = $Config.Conditions | ConvertFrom-Json | Where-Object { $Config.Input.value -ne '' } + $actions = $Config.Actions + $conditionStrings = [System.Collections.Generic.List[string]]::new() + $CIPPClause = [System.Collections.Generic.List[string]]::new() + $AddedLocationCondition = $false + foreach ($condition in $conditions) { + if ($condition.Property.label -eq 'CIPPGeoLocation' -and !$AddedLocationCondition) { + $conditionStrings.Add("`$_.HasLocationData -eq `$true") + $CIPPClause.Add('HasLocationData is true') + $AddedLocationCondition = $true } - "@($($arrayAsString -join ', '))" - } else { "'$($condition.Input.value)'" } + $value = if ($condition.Input.value -is [array]) { + $arrayAsString = $condition.Input.value | ForEach-Object { + "'$_'" + } + "@($($arrayAsString -join ', '))" + } else { "'$($condition.Input.value)'" } - $conditionStrings.Add("`$(`$_.$($condition.Property.label)) -$($condition.Operator.value) $value") - $CIPPClause.Add("$($condition.Property.label) is $($condition.Operator.label) $value") - } - $finalCondition = $conditionStrings -join ' -AND ' + $conditionStrings.Add("`$(`$_.$($condition.Property.label)) -$($condition.Operator.value) $value") + $CIPPClause.Add("$($condition.Property.label) is $($condition.Operator.label) $value") + } + $finalCondition = $conditionStrings -join ' -AND ' - [PSCustomObject]@{ - clause = $finalCondition - expectedAction = $actions - CIPPClause = $CIPPClause + [PSCustomObject]@{ + clause = $finalCondition + expectedAction = $actions + CIPPClause = $CIPPClause + } } - + } catch { + Write-Warning "Error creating where clause: $($_.Exception.Message)" + Write-Information $_.InvocationInfo.PositionMessage + #Write-LogMessage -API 'Webhooks' -message 'Error creating where clause' -LogData (Get-CippException -Exception $_) -sev Error -tenant $TenantFilter + throw $_ } $MatchedRules = [System.Collections.Generic.List[string]]::new() diff --git a/Modules/CippExtensions/Public/Extension Functions/Get-ExtensionAPIKey.ps1 b/Modules/CippExtensions/Public/Extension Functions/Get-ExtensionAPIKey.ps1 index f10c4775a2f3..f9f7cc2b7901 100644 --- a/Modules/CippExtensions/Public/Extension Functions/Get-ExtensionAPIKey.ps1 +++ b/Modules/CippExtensions/Public/Extension Functions/Get-ExtensionAPIKey.ps1 @@ -11,7 +11,7 @@ function Get-ExtensionAPIKey { ) $Var = "Ext_$Extension" - $APIKey = Get-Item -Path "ENV:$Var" -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Value + $APIKey = Get-Item -Path "env:$Var" -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Value if ($APIKey) { Write-Information "Using cached API Key for $Extension" } else { @@ -20,13 +20,13 @@ function Get-ExtensionAPIKey { $DevSecretsTable = Get-CIPPTable -tablename 'DevSecrets' $APIKey = (Get-CIPPAzDataTableEntity @DevSecretsTable -Filter "PartitionKey eq '$Extension' and RowKey eq '$Extension'").APIKey } else { - $keyvaultname = ($ENV:WEBSITE_DEPLOYMENT_ID -split '-')[0] + $keyvaultname = ($env:WEBSITE_DEPLOYMENT_ID -split '-')[0] $null = Connect-AzAccount -Identity - $SubscriptionId = $ENV:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 + $SubscriptionId = $env:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 $null = Set-AzContext -SubscriptionId $SubscriptionId $APIKey = (Get-AzKeyVaultSecret -VaultName $keyvaultname -Name $Extension -AsPlainText) } - Set-Item -Path "ENV:$Var" -Value $APIKey -Force -ErrorAction SilentlyContinue + Set-Item -Path "env:$Var" -Value $APIKey -Force -ErrorAction SilentlyContinue } return $APIKey } diff --git a/Modules/CippExtensions/Public/Extension Functions/Set-ExtensionAPIKey.ps1 b/Modules/CippExtensions/Public/Extension Functions/Set-ExtensionAPIKey.ps1 index 59b741f9c52a..191b4182e288 100644 --- a/Modules/CippExtensions/Public/Extension Functions/Set-ExtensionAPIKey.ps1 +++ b/Modules/CippExtensions/Public/Extension Functions/Set-ExtensionAPIKey.ps1 @@ -23,13 +23,13 @@ function Set-ExtensionAPIKey { } Add-CIPPAzDataTableEntity @DevSecretsTable -Entity $Secret -Force } else { - $keyvaultname = ($ENV:WEBSITE_DEPLOYMENT_ID -split '-')[0] + $keyvaultname = ($env:WEBSITE_DEPLOYMENT_ID -split '-')[0] $null = Connect-AzAccount -Identity - $SubscriptionId = $ENV:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 + $SubscriptionId = $env:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 $null = Set-AzContext -SubscriptionId $SubscriptionId $null = Set-AzKeyVaultSecret -VaultName $keyvaultname -Name $Extension -SecretValue (ConvertTo-SecureString -AsPlainText -Force -String $APIKey) } - Set-Item -Path "ENV:$Var" -Value $APIKey -Force -ErrorAction SilentlyContinue + Set-Item -Path "env:$Var" -Value $APIKey -Force -ErrorAction SilentlyContinue } return $true } diff --git a/Modules/CippExtensions/Public/Gradient/Get-GradientToken.ps1 b/Modules/CippExtensions/Public/Gradient/Get-GradientToken.ps1 index d59430b67a79..5965ec745c10 100644 --- a/Modules/CippExtensions/Public/Gradient/Get-GradientToken.ps1 +++ b/Modules/CippExtensions/Public/Gradient/Get-GradientToken.ps1 @@ -4,9 +4,9 @@ function Get-GradientToken { ) if ($Configuration.vendorKey) { $null = Connect-AzAccount -Identity - $SubscriptionId = $ENV:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 + $SubscriptionId = $env:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 $null = Set-AzContext -SubscriptionId $SubscriptionId - $keyvaultname = ($ENV:WEBSITE_DEPLOYMENT_ID -split '-')[0] + $keyvaultname = ($env:WEBSITE_DEPLOYMENT_ID -split '-')[0] $partnerApiKey = (Get-AzKeyVaultSecret -VaultName $keyvaultname -Name 'Gradient' -AsPlainText) $authorizationToken = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("$($configuration.vendorKey):$($partnerApiKey)")) diff --git a/Modules/CippExtensions/Public/HIBP/Get-HIBPAuth.ps1 b/Modules/CippExtensions/Public/HIBP/Get-HIBPAuth.ps1 index 69bc4f3fec45..c759e08ded55 100644 --- a/Modules/CippExtensions/Public/HIBP/Get-HIBPAuth.ps1 +++ b/Modules/CippExtensions/Public/HIBP/Get-HIBPAuth.ps1 @@ -1,37 +1,38 @@ function Get-HIBPAuth { $Var = 'Ext_HIBP' - $APIKey = Get-Item -Path "ENV:$Var" -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Value + $APIKey = Get-Item -Path "env:$Var" -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Value if ($APIKey) { Write-Information 'Using cached API Key for HIBP' + $Secret = $APIKey } else { if ($env:AzureWebJobsStorage -eq 'UseDevelopmentStorage=true') { $DevSecretsTable = Get-CIPPTable -tablename 'DevSecrets' $Secret = (Get-CIPPAzDataTableEntity @DevSecretsTable -Filter "PartitionKey eq 'HIBP' and RowKey eq 'HIBP'").APIKey } else { $null = Connect-AzAccount -Identity - $SubscriptionId = $ENV:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 + $SubscriptionId = $env:WEBSITE_OWNER_NAME -split '\+' | Select-Object -First 1 $null = Set-AzContext -SubscriptionId $SubscriptionId - $VaultName = ($ENV:WEBSITE_DEPLOYMENT_ID -split '-')[0] + $VaultName = ($env:WEBSITE_DEPLOYMENT_ID -split '-')[0] try { $Secret = Get-AzKeyVaultSecret -VaultName $VaultName -Name 'HIBP' -AsPlainText -ErrorAction Stop } catch { $Secret = $null } - if ([string]::IsNullOrEmpty($Secret) -and $ENV:CIPP_HOSTED -eq 'true') { + if ([string]::IsNullOrEmpty($Secret) -and $env:CIPP_HOSTED -eq 'true') { $VaultName = 'hibp-kv' - if ($SubscriptionId -ne $ENV:CIPP_HOSTED_KV_SUB -and $ENV:CIPP_HOSTED_KV_SUB -match '^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$') { - $null = Set-AzContext -SubscriptionId $ENV:CIPP_HOSTED_KV_SUB + if ($SubscriptionId -ne $env:CIPP_HOSTED_KV_SUB -and $env:CIPP_HOSTED_KV_SUB -match '^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$') { + $null = Set-AzContext -SubscriptionId $env:CIPP_HOSTED_KV_SUB } $Secret = Get-AzKeyVaultSecret -VaultName $VaultName -Name 'HIBP' -AsPlainText } } - Set-Item -Path "ENV:$Var" -Value $APIKey -Force -ErrorAction SilentlyContinue + Set-Item -Path "env:$Var" -Value $APIKey -Force -ErrorAction SilentlyContinue } return @{ - 'User-Agent' = "CIPP-$($ENV:TenantID)" + 'User-Agent' = "CIPP-$($env:TenantID)" 'Accept' = 'application/json' 'api-version' = '3' 'hibp-api-key' = $Secret diff --git a/Modules/CippExtensions/Public/Halo/Set-HaloMapping.ps1 b/Modules/CippExtensions/Public/Halo/Set-HaloMapping.ps1 index 30ae54a5e310..48d75df2af63 100644 --- a/Modules/CippExtensions/Public/Halo/Set-HaloMapping.ps1 +++ b/Modules/CippExtensions/Public/Halo/Set-HaloMapping.ps1 @@ -9,15 +9,16 @@ function Set-HaloMapping { Remove-AzDataTableEntity -Force @CIPPMapping -Entity $_ } foreach ($Mapping in $Request.Body) { - $AddObject = @{ - PartitionKey = 'HaloMapping' - RowKey = "$($mapping.TenantId)" - IntegrationId = "$($mapping.IntegrationId)" - IntegrationName = "$($mapping.IntegrationName)" + if ($Mapping.TenantId) { + $AddObject = @{ + PartitionKey = 'HaloMapping' + RowKey = "$($mapping.TenantId)" + IntegrationId = "$($mapping.IntegrationId)" + IntegrationName = "$($mapping.IntegrationName)" + } } Add-CIPPAzDataTableEntity @CIPPMapping -Entity $AddObject -Force - Write-LogMessage -API $APINAME -headers $Request.Headers -message "Added mapping for $($mapping.name)." -Sev 'Info' } $Result = [pscustomobject]@{'Results' = 'Successfully edited mapping table.' } diff --git a/Modules/CippExtensions/Public/NinjaOne/Invoke-NinjaOneTenantSync.ps1 b/Modules/CippExtensions/Public/NinjaOne/Invoke-NinjaOneTenantSync.ps1 index 226db439b596..fe45288c05e7 100644 --- a/Modules/CippExtensions/Public/NinjaOne/Invoke-NinjaOneTenantSync.ps1 +++ b/Modules/CippExtensions/Public/NinjaOne/Invoke-NinjaOneTenantSync.ps1 @@ -2141,4 +2141,5 @@ function Invoke-NinjaOneTenantSync { $CurrentItem | Add-Member -NotePropertyName lastStatus -NotePropertyValue 'Failed' -Force Add-CIPPAzDataTableEntity @MappingTable -Entity $CurrentItem -Force } + return $true } diff --git a/Modules/CippExtensions/Public/NinjaOne/Push-NinjaOneQueue.ps1 b/Modules/CippExtensions/Public/NinjaOne/Push-NinjaOneQueue.ps1 index 09fe668a97b4..470220016842 100644 --- a/Modules/CippExtensions/Public/NinjaOne/Push-NinjaOneQueue.ps1 +++ b/Modules/CippExtensions/Public/NinjaOne/Push-NinjaOneQueue.ps1 @@ -11,5 +11,5 @@ function Push-NinjaOneQueue { 'SyncTenant' { Invoke-NinjaOneTenantSync -QueueItem $Item } 'SyncTenants' { Invoke-NinjaOneSync } } - -} \ No newline at end of file + return $true +} diff --git a/Modules/CippExtensions/Public/NinjaOne/Set-NinjaOneOrgMapping.ps1 b/Modules/CippExtensions/Public/NinjaOne/Set-NinjaOneOrgMapping.ps1 index b0798eca8230..ab2e745c8417 100644 --- a/Modules/CippExtensions/Public/NinjaOne/Set-NinjaOneOrgMapping.ps1 +++ b/Modules/CippExtensions/Public/NinjaOne/Set-NinjaOneOrgMapping.ps1 @@ -10,15 +10,15 @@ function Set-NinjaOneOrgMapping { Remove-AzDataTableEntity -Force @CIPPMapping -Entity $_ } foreach ($Mapping in $Request.Body) { - $AddObject = @{ - PartitionKey = 'NinjaOneMapping' - RowKey = "$($mapping.TenantId)" - IntegrationId = "$($mapping.IntegrationId)" - IntegrationName = "$($mapping.IntegrationName)" + if ($Mapping.TenantId) { + $AddObject = @{ + PartitionKey = 'NinjaOneMapping' + RowKey = "$($mapping.TenantId)" + IntegrationId = "$($mapping.IntegrationId)" + IntegrationName = "$($mapping.IntegrationName)" + } } - Add-CIPPAzDataTableEntity @CIPPMapping -Entity $AddObject -Force - Write-LogMessage -API $APINAME -headers $Request.Headers -message "Added mapping for $($mapping.name)." -Sev 'Info' } $Result = [pscustomobject]@{'Results' = 'Successfully edited mapping table.' } diff --git a/Modules/CippExtensions/Public/Sherweb/Test-SherwebMigrationAccounts.ps1 b/Modules/CippExtensions/Public/Sherweb/Test-SherwebMigrationAccounts.ps1 index d549a6599926..5a44c7b5cf4d 100644 --- a/Modules/CippExtensions/Public/Sherweb/Test-SherwebMigrationAccounts.ps1 +++ b/Modules/CippExtensions/Public/Sherweb/Test-SherwebMigrationAccounts.ps1 @@ -5,15 +5,16 @@ function Test-SherwebMigrationAccounts { ) $Table = Get-CIPPTable -TableName Extensionsconfig - $Config = ((Get-CIPPAzDataTableEntity @Table).config | ConvertFrom-Json).Sherweb + $ExtensionConfig = (Get-CIPPAzDataTableEntity @Table).config | ConvertFrom-Json + $Config = $ExtensionConfig.Sherweb #First get a list of all subscribed skus for this tenant, that are in the transfer window. - $Licenses = (Get-CIPPLicenseOverview -TenantFilter $TenantFilter) | ForEach-Object { $_.terminfo = ($_.terminfo | ConvertFrom-Json -ErrorAction SilentlyContinue) ; $_ } | Where-Object { $_.terminfo -ne $null -and $_.terminfo.TransferWindow -LE 78 } + $Licenses = (Get-CIPPLicenseOverview -TenantFilter $TenantFilter) | ForEach-Object { $_.terminfo = ($_.terminfo | ConvertFrom-Json -ErrorAction SilentlyContinue) ; $_ } | Where-Object { $_.terminfo -ne $null -and $_.terminfo.TransferWindow -le 7 } #now check if this exact count of licenses is available at Sherweb, if not, we need to migrate them. $SherwebLicenses = Get-SherwebCurrentSubscription -TenantFilter $TenantFilter $LicencesToMigrate = foreach ($License in $Licenses) { foreach ($termInfo in $License.terminfo) { - $matchedSherweb = $SherwebLicenses | Where-Object { $_.quantity -eq 3 -and $_.commitmentTerm.termEndDate -eq $termInfo.NextLifecycle } + $matchedSherweb = $SherwebLicenses | Where-Object { $_.quantity -eq $termInfo.TotalLicenses -and $_.commitmentTerm.termEndDate -eq $termInfo.NextLifecycle } if (-not $matchedSherweb) { [PSCustomObject]@{ LicenseName = ($Licenses | Where-Object { $_.skuId -eq $License.skuId }).license @@ -31,19 +32,60 @@ function Test-SherwebMigrationAccounts { switch -wildcard ($config.migrationMethods) { '*notify*' { + $Subject = "Sherweb Migration: $($TenantFilter) - $($LicencesToMigrate.Count) licenses to migrate" $HTMLContent = New-CIPPAlertTemplate -Data $LicencesToMigrate -Format 'html' -InputObject 'sherwebmig' $JSONContent = New-CIPPAlertTemplate -Data $LicencesToMigrate -Format 'json' -InputObject 'sherwebmig' Send-CIPPAlert -Type 'email' -Title $Subject -HTMLContent $HTMLContent.htmlcontent -TenantFilter $tenant -APIName 'Alerts' Send-CIPPAlert -Type 'psa' -Title $Subject -HTMLContent $HTMLContent.htmlcontent -TenantFilter $standardsTenant -APIName 'Alerts' Send-CIPPAlert -Type 'webhook' -JSONContent $JSONContent -TenantFilter $Tenant -APIName 'Alerts' } - 'buyAndNotify' { - #Buy the licenses at Sherweb using the matching CSV. + '*buy*' { + try { + $PotentialLicenses = Get-SherwebCatalog -TenantFilter $TenantFilter | Where-Object { $_.microsoftSkuId -in $LicencesToMigrate.SkuId -and $_.sku -like "*$($Config.migrateToLicense)" } + if (!$PotentialLicenses) { + throw 'cannot buy new license: no matching license found in catalog' + } else { + $PotentialLicenses | ForEach-Object { + Set-SherwebSubscription -TenantFilter $TenantFilter -SKU $PotentialLicenses.sku -Quantity $LicencesToMigrate.TotalLicensesAtUnknownCSP + } + } + } catch { + $Subject = "Sherweb Migration: $($TenantFilter) - Failed to buy licenses." + $HTMLContent = New-CIPPAlertTemplate -Data $LicencesToMigrate -Format 'html' -InputObject 'sherwebmigBuyFail' + $JSONContent = New-CIPPAlertTemplate -Data $LicencesToMigrate -Format 'json' -InputObject 'sherwebmigBuyFail' + Send-CIPPAlert -Type 'email' -Title $Subject -HTMLContent $HTMLContent.htmlcontent -TenantFilter $tenant -APIName 'Alerts' + Send-CIPPAlert -Type 'psa' -Title $Subject -HTMLContent $HTMLContent.htmlcontent -TenantFilter $standardsTenant -APIName 'Alerts' + Send-CIPPAlert -Type 'webhook' -JSONContent $JSONContent -TenantFilter $Tenant -APIName 'Alerts' + } + } - 'buyAndCancel' { - #Create HTML report for this tenant. Send to webhook/notifications/etc - #Buy the licenses at Sherweb using the matching CSV. - #Cancel the licenses in old vendor. + '*Cancel' { + try { + $tenantid = (Get-Tenants -TenantFilter $TenantFilter).customerId + $Pax8Config = $ExtensionConfig.Pax8 + $Pax8ClientId = $Pax8Config.clientId + $Pax8ClientSecret = Get-ExtensionAPIKey -Extension 'Pax8' + $paxBody = @{ + client_id = $Pax8ClientId + client_secret = $Pax8ClientSecret + audience = 'https://api.pax8.com' + grant_type = 'client_credentials' + } + $Token = Invoke-RestMethod -Uri 'https://api.pax8.com/v1/token' -Method POST -Headers $headers -ContentType 'application/json' -Body $paxBody + $headers = @{ Authorization = "Bearer $($Token.access_token)" } + $cancelSubList = Invoke-RestMethod -Uri "https://api.pax8.com/v1/subscriptions?page=0&size=10&status=Active&companyId=$($tenantid)" -Method GET -Headers $headers | Where-Object -Property productId -In $LicencesToMigrate.SkuId + $cancelSubList | ForEach-Object { + $response = Invoke-RestMethod -Uri "https://api.pax8.com/v1/subscriptions/$($_.subscriptionId)" -Method DELETE -Headers $headers -ContentType 'application/json' -Body ($body | ConvertTo-Json) + } + + } catch { + $Subject = 'Sherweb Migration: Pax Migration failed' + $HTMLContent = New-CIPPAlertTemplate -Data $LicencesToMigrate -Format 'html' -InputObject 'sherwebmigfailpax' + $JSONContent = New-CIPPAlertTemplate -Data $LicencesToMigrate -Format 'json' -InputObject 'sherwebmigfailpax' + Send-CIPPAlert -Type 'email' -Title $Subject -HTMLContent $HTMLContent.htmlcontent -TenantFilter $tenant -APIName 'Alerts' + Send-CIPPAlert -Type 'psa' -Title $Subject -HTMLContent $HTMLContent.htmlcontent -TenantFilter $standardsTenant -APIName 'Alerts' + Send-CIPPAlert -Type 'webhook' -JSONContent $JSONContent -TenantFilter $Tenant -APIName 'Alerts' + } } } diff --git a/Tools/Update-LicenseSKUFiles.ps1 b/Tools/Update-LicenseSKUFiles.ps1 index e3f41a4df698..e21817d57f18 100644 --- a/Tools/Update-LicenseSKUFiles.ps1 +++ b/Tools/Update-LicenseSKUFiles.ps1 @@ -24,7 +24,7 @@ Needs to be run from the "Tools" folder in the CIPP-API project. # Download the latest license SKU CSV file from Microsoft. Saved to the TEMP folder to circumvent a bug where "???" is added to the first property name. $licenseCsvURL = 'https://download.microsoft.com/download/e/3/e/e3e9faf2-f28b-490a-9ada-c6089a1fc5b0/Product%20names%20and%20service%20plan%20identifiers%20for%20licensing.csv' -$TempLicenseDataFile = "$ENV:TEMP\LicenseSKUs.csv" +$TempLicenseDataFile = "$env:TEMP\LicenseSKUs.csv" Invoke-WebRequest -Uri $licenseCsvURL -OutFile $TempLicenseDataFile $LicenseDataFile = Get-Item -Path $TempLicenseDataFile $LicenseData = Import-Csv -Path $LicenseDataFile.FullName -Encoding utf8BOM -Delimiter ',' diff --git a/Tools/Update-StandardsComments.ps1 b/Tools/Update-StandardsComments.ps1 index e804aefe0998..08493bda4fbe 100644 --- a/Tools/Update-StandardsComments.ps1 +++ b/Tools/Update-StandardsComments.ps1 @@ -107,7 +107,15 @@ foreach ($Standard in $StandardsInfo) { } continue } - $NewComment.Add(" $(EscapeMarkdown($Property.Value.ToString()))`n") + elseif ($Property.Value -is [System.Management.Automation.PSCustomObject]) { + $NewComment.Add(" $(ConvertTo-Json -InputObject $Property.Value -Depth 5 -Compress)`n") + continue + } + else { + if ($null -ne $Property.Value) { + $NewComment.Add(" $(EscapeMarkdown($Property.Value.ToString()))`n") + } + } } } diff --git a/cspell.json b/cspell.json new file mode 100644 index 000000000000..376f61639b3f --- /dev/null +++ b/cspell.json @@ -0,0 +1,69 @@ +{ + "version": "0.2", + "ignorePaths": [], + "dictionaryDefinitions": [], + "dictionaries": [], + "words": [ + "Intune", + "Entra", + "GDAP", + "CIPP", + "CIPP-API", + "OBEE", + "TNEF", + "winmail", + "AITM", + "Yubikey", + "Sherweb", + "Autotask", + "Connectwise", + "Datto", + "Bluetrait", + "ADMS", + "SSPR", + "PSTN", + "Passwordless", + ], + "ignoreWords": [ + "tenantid", + "APINAME", + "CIPPBPA", + "CIPPCA", + "CIPPSPO", + "CIPPAPI", + "Addins", + "Helptext", + "ADDEDCOMPONENT", + "ADDEDDATE", + "POWERSHELLEQUIVALENT", + "RECOMMENDEDBY", + "UPDATECOMMENTBLOCK", + "DISABLEDFEATURES", + "pscustomobject", + "microsoftonline", + "mdo_safeattachments", + "mdo_highconfidencespamaction", + "mdo_highconfidencephishaction", + "mdo_phisspamacation", + "mdo_spam_notifications_only_for_admins", + "mdo_antiphishingpolicies", + "mdo_phishthresholdlevel", + "mdo_autoforwardingmode", + "mdo_blockmailforward", + "mdo_zapspam", + "mdo_zapphish", + "mdo_zapmalware", + "mdo_safedocuments", + "mdo_commonattachmentsfilter", + "mdo_safeattachmentpolicy", + "mdo_safelinksforemail", + "mdo_safelinksforOfficeApps", + "exo_storageproviderrestricted", + "exo_individualsharing", + "exo_outlookaddins", + "exo_mailboxaudit", + "exo_mailtipsenabled", + "mip_search_auditlog", + ], + "import": [] +} diff --git a/profile.ps1 b/profile.ps1 index 5230a3b5561d..9fa3401f75db 100644 --- a/profile.ps1 +++ b/profile.ps1 @@ -38,7 +38,7 @@ try { } catch {} try { - if (!$ENV:SetFromProfile) { + if (!$env:SetFromProfile) { Write-Information "We're reloading from KV" $Auth = Get-CIPPAuthentication } diff --git a/version_latest.txt b/version_latest.txt index f8cb1fa110da..18bb4182dd01 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -7.4.2 +7.5.0