diff --git a/.gitignore b/.gitignore index a807be8c00b6..4bb4cb1069b0 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,7 @@ Logs ExcludedTenants SendNotifications/config.json .env + + +# Cursor IDE +.cursor/rules diff --git a/ConversionTable.csv b/ConversionTable.csv index 704f7c507d5f..5b7cea1f09ea 100644 --- a/ConversionTable.csv +++ b/ConversionTable.csv @@ -20,6 +20,7 @@ Clipchamp Premium,Clipchamp_Premium,0fe440c5-f2bf-442b-a4f4-9a7af77a200b,ONEDRIV Clipchamp Standard,Clipchamp_Standard,481f3bc2-5756-4b28-9375-5c8c86b99e6b,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Clipchamp Standard,Clipchamp_Standard,481f3bc2-5756-4b28-9375-5c8c86b99e6b,CLIPCHAMP,a1ace008-72f3-4ea0-8dac-33b3a23a2472,Microsoft Clipchamp Clipchamp Standard,Clipchamp_Standard,481f3bc2-5756-4b28-9375-5c8c86b99e6b,ONEDRIVECLIPCHAMP,f7e5b77d-f293-410a-bae8-f941f19fe680,OneDrive for Business (Clipchamp) +Clipchamp Premium Add-on,Clipchamp_Premium_Add_on,4b2c20e4-939d-4bf4-9dd8-6870240cfe19,CLIPCHAMP_PREMIUM,430b908f-78e1-4812-b045-cf83320e7d5d,Microsoft Clipchamp Premium Microsoft 365 Audio Conferencing,MCOMEETADV,0c266dff-15dd-4b49-8397-2bb16070ed52,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing Microsoft Entra ID Basic,AAD_BASIC,2b9c8e7c-319c-43a2-a2a0-48c5c6161de7,AAD_BASIC,c4da7f8a-5ee2-4c99-a7e1-87d2df57f6fe,Microsoft Entra BASIC Microsoft Entra ID P1,AAD_PREMIUM,078d2b04-f1bd-4111-bbd4-b4b1b354cef4,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 @@ -418,6 +419,13 @@ Dynamics 365 Guides vTrial,Dynamics_365_Guides_vTrial,99cb3f83-fbec-4aa1-8262-96 Dynamics 365 Guides vTrial,Dynamics_365_Guides_vTrial,99cb3f83-fbec-4aa1-8262-9679e6df7c53,DYN365_CDS_VIRAL,17ab22cd-a0b3-4536-910a-cb6eb12696c0,Common Data Service Dynamics 365 Guides vTrial,Dynamics_365_Guides_vTrial,99cb3f83-fbec-4aa1-8262-9679e6df7c53,POWER_APPS_DYN365_VIRAL_TRIAL_MIXED_REALITY,066e2fd1-ba15-40e7-aa96-d6636b1cdf71,Power Apps for Dynamics 365 Mixed Reality Dynamics 365 Guides vTrial,Dynamics_365_Guides_vTrial,99cb3f83-fbec-4aa1-8262-9679e6df7c53,POWER_AUTOMATE_DYN365_VIRAL_TRIAL_MIXED_REALITY,26fa8a18-2812-4b3d-96b4-864818ce26be,Power Automate for Dynamics 365 Mixed Reality +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,Forms_Pro_Talent,1c4ae475-5608-43fa-b3f7-d20e07cf24b4,Microsoft Dynamics 365 Customer Voice for Talent +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,D365_HR_SELF_SERVICE_OPS,835b837b-63c1-410e-bf6b-bdef201ad129,Dynamics 365 Human Resource Self Service +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,D365_HR_OPS,8b21a5dc-5485-49ed-a2d4-0e772c830f6d,Dynamics 365 Human Resources +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,D365_HR_Attach,3219525a-4064-45ec-9c35-a33ea6b39a49,Dynamics 365 Human Resources Attach +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,D365_HR_ATTACH_OPS,90d8cb62-e98a-4639-8342-8c7d2c8215ba,Dynamics 365 Human Resources Attach License +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 Hybrid Connector,CRM_HYBRIDCONNECTOR,de176c31-616d-4eae-829a-718918d7ec23,CRM_HYBRIDCONNECTOR,0210d5c8-49d2-4dd1-a01b-a91c7c14e0bf,CRM Hybrid Connector Dynamics 365 Hybrid Connector,CRM_HYBRIDCONNECTOR,de176c31-616d-4eae-829a-718918d7ec23,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 for Marketing Additional Application,DYN365_MARKETING_APPLICATION_ADDON,99c5688b-6c75-4496-876f-07f0fbd69add,DYN365_MARKETING_APPLICATION_ADDON,51cf0638-4861-40c0-8b20-1161ab2f80be,Dynamics 365 for Marketing Additional Application @@ -967,111 +975,129 @@ Microsoft 365 A3 - Unattended License for students use benefit,M365EDU_A3_STUUSE Microsoft 365 A3 - Unattended License for students use benefit,M365EDU_A3_STUUSEBNFT_RPA1,1aa94593-ca12-4254-a738-81a5972958e8,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune for Education Microsoft 365 A3 - Unattended License for students use benefit,M365EDU_A3_STUUSEBNFT_RPA1,1aa94593-ca12-4254-a738-81a5972958e8,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 Microsoft 365 A3 - Unattended License for students use benefit,M365EDU_A3_STUUSEBNFT_RPA1,1aa94593-ca12-4254-a738-81a5972958e8,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CDS_O365_P3,afa73018-811e-46e9-988f-f75d2b1b8430,Common Data Service for Teams -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,LOCKBOX_ENTERPRISE,9f431833-0334-42de-a7dc-70aa40db46db,Customer Lockbox -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_Exchange,cd31b152-6326-4d1b-ae1b-997b625182e6,Data Classification in Microsoft 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCHANGE_S_ENTERPRISE,efb87545-963c-4e0d-99df-69c6916d9eb0,Exchange Online (Plan 2) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Content_Explorer,d9fa6af4-e046-4c89-9226-729a0786685d,Information Protection and Governance Analytics - Premium -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ContentExplorer_Standard,2b815d45-56e4-4e3a-b65c-66cb9175b560,Information Protection and Governance Analytics – Standard -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_CLP2,efb0351d-3b08-4503-993d-383af8de41e3,Information Protection for Office 365 - Premium -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_CLP1,5136a095-5cf0-4aff-bec3-e84448b38ea5,Information Protection for Office 365 - Standard -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,M365_ADVANCED_AUDITING,2f442157-a11c-46b9-ae5b-6e39ff4e5849,Microsoft 365 Advanced Auditing -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,OFFICESUBSCRIPTION,43de0ff5-c92c-492b-9116-175376d08c38,Microsoft 365 Apps for Enterprise -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_COMMUNICATION_COMPLIANCE,a413a9ff-720c-4822-98ef-2f37c2a21f4c,Microsoft 365 Communication Compliance -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MTP,bf28f719-7844-4079-9c78-c1307898e192,Microsoft 365 Defender -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFTBOOKINGS,199a5c09-e0ca-4e37-8f7c-b05d533e1ea2,Microsoft Bookings -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMUNICATIONS_DLP,6dc145d6-95dd-4191-b9c3-185575ee6f6b,Microsoft Communications DLP -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CUSTOMER_KEY,6db1f1db-2b46-403f-be40-e39395f08dbb,Microsoft Customer Key -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,DATA_INVESTIGATIONS,46129a58-a698-46f0-aa5b-17f6586297d9,Microsoft Data Investigations -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ATP_ENTERPRISE,f20fedf3-f3c3-43c3-8267-2bfdd51c0939,Microsoft Defender for Office 365 (Plan 1) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,THREAT_INTELLIGENCE,8e0c0a52-6a6c-4d40-8370-dd62790dcd70,Microsoft Defender for Office 365 (Plan 2) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCEL_PREMIUM,531ee2f8-b1cb-453b-9c21-d2180d014ca5,Microsoft Excel Advanced Analytics -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,OFFICE_FORMS_PLAN_3,96c1e14a-ef43-418d-b115-9636cdaa8eed,Microsoft Forms (Plan 3) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INFO_GOVERNANCE,e26c2fcc-ab91-4a61-b35c-03cdc8dddf66,Microsoft Information Governance -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INSIDER_RISK,d587c7a3-bda9-4f99-8776-9bcf59c84f75,Microsoft Insider Risk Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,KAIZALA_STANDALONE,0898bdbb-73b0-471a-81e5-20f1fe4dd66e,Microsoft Kaizala Pro -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ML_CLASSIFICATION,d2d51368-76c9-4317-ada2-a12c004c432f,Microsoft ML-Based Classification -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCHANGE_ANALYTICS,34c0d7a0-a70f-4668-9238-47f9fc208882,Microsoft MyAnalytics (Full) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RECORDS_MANAGEMENT,65cc641f-cccd-4643-97e0-a17e3045e541,Microsoft Records Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_SEARCH,94065c59-bc8e-4e8b-89e5-5138d471eaff,Microsoft Search -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Deskless,8c7d2df8-86f0-4902-b2ed-a0458298f3b3,Microsoft StaffHub -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,STREAM_O365_E5,6c6042f5-6f01-4d67-b8c1-eb99d36eed3e,Microsoft Stream for Office 365 E5 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,TEAMS1,57ff2da0-773e-42df-b2af-ffb7a2317929,Microsoft Teams -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MINECRAFT_EDUCATION_EDITION,4c246bbc-f513-4311-beff-eba54c353256,Minecraft Education Edition -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_O365,882e1d05-acd1-4ccb-8708-6ee03664b117,Mobile Device Management for Office 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Nucleus,db4d623d-b514-490b-b7ef-8885eee514de,Nucleus -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EQUIVIO_ANALYTICS,4de31727-a228-4ec3-a5bf-8e45b5ca48cc,Office 365 Advanced eDiscovery -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ADALLOM_S_O365,8c098270-9dd4-4350-9b30-ba4703f3b36b,Office 365 Cloud App Security -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PAM_ENTERPRISE,b1188c4c-1b36-4018-b48b-ee07604f6feb,Office 365 Privileged Access Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SAFEDOCS,bf6f5520-59e3-4f82-974b-7dbbc4fd27c7,Office 365 SafeDocs -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SHAREPOINTWAC_EDU,e03c7e47-402c-463c-ab25-949079bedb21,Office for the Web for Education -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,POWERAPPS_O365_P3,9c0dab89-a30c-4117-86e7-97bda240acd2,Power Apps for Office 365 (Plan 3) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,BI_AZURE_P2,70d33638-9c74-4d01-bfd3-562de28bd4ba,Power BI Pro -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PREMIUM_ENCRYPTION,617b097b-4b93-4ede-83de-5f075bb5fb2f,Premium Encryption in Office 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PROJECT_O365_P3,b21a6b06-1988-436e-a07b-51ec6d9f52ad,Project for Office (Plan E5) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMUNICATIONS_COMPLIANCE,41fcdd7d-4733-4863-9cf4-c65b83ce2df4,Microsoft Communications Compliance -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INSIDER_RISK_MANAGEMENT,9d0c4ee5-e4a1-4625-ab39-d82b619b1a34,Microsoft Insider Risk Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SCHOOL_DATA_SYNC_P2,500b6a2a-7a50-4f40-b5f9-160e5b8c2f48,School Data Sync (Plan 2) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SHAREPOINTENTERPRISE_EDU,63038b2c-28d0-45f6-bc36-33062963b498,SharePoint (Plan 2) for Education -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SWAY,a23b959c-7ce8-4e57-9140-b90eb88a9e97,Sway -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,BPOS_S_TODO_3,3fb82609-8c27-4f7b-bd51-30634711ee67,To-Do (Plan 3) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,VIVA_LEARNING_SEEDED,b76fb638-6ba6-402a-b9f9-83d28acb3d86,Viva Learning Seeded -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WHITEBOARD_PLAN3,4a51bca5-1eff-43f5-878c-177680f191af,Whiteboard (Plan 3) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WINDEFATP,871d91ec-ec1a-452b-a83f-bd76c7d770ef,Microsoft Defender for Endpoint -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFTENDPOINTDLP,64bfac92-2b17-4482-b5e5-a0304429de3e,Microsoft Endpoint DLP -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,UNIVERSAL_PRINT_01,795f6fe0-cc4d-4773-b050-5dde4dc704c9,Universal Print -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Virtualization Rights for Windows 10 (E3/E5+VDA),e7c91390-7625-45be-94e0-e16907e03118,Windows 10/11 Enterprise -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WINDOWSUPDATEFORBUSINESS_DEPLOYMENTSERVICE,7bf960f6-2cd9-443a-8046-5dbff9558365,Windows Update for Business Deployment Service -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_PREMIUM_P2,eec0eb4f-6444-4f95-aba0-50c24d67f998,Microsoft Entra ID P2 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_PREMIUM,6c57d4b6-3b23-47a5-9bc9-69f17b4947b3,Azure Information Protection Premium P1 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_PREMIUM2,5689bec4-755d-4753-8b61-40975025187c,Azure Information Protection Premium P2 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,DYN365_CDS_O365_P3,28b0fa46-c39a-4188-89e2-58e979a6b014,Common Data Service -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MFA_PREMIUM,8a256a2b-b617-496d-b51b-e76466e88db0,Microsoft Azure Multi-Factor Authentication -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ADALLOM_S_STANDALONE,2e2ddb96-6af9-4b1d-a3f0-d6ecfd22edb2,Microsoft Defender for Cloud Apps -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ATA,14ab5db5-e6c4-4b20-b4bc-13e36fd2227f,Microsoft Defender for Identity -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune for Education -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,FLOW_O365_P3,07699545-9485-468e-95b6-2fca3738be01,Power Automate for Office 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,POWER_VIRTUAL_AGENTS_O365_P3,ded3d325-1bdc-453e-8432-5bac26d7a014,Power Virtual Agents for Office 365 -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CDS_O365_P3,afa73018-811e-46e9-988f-f75d2b1b8430,Common Data Service for Teams +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,LOCKBOX_ENTERPRISE,9f431833-0334-42de-a7dc-70aa40db46db,Customer Lockbox +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CustomerLockboxA_Enterprise,3ec18638-bd4c-4d3b-8905-479ed636b83e,Customer Lockbox (A) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_Exchange,cd31b152-6326-4d1b-ae1b-997b625182e6,Data Classification in Microsoft 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMON_DEFENDER_PLATFORM_FOR_OFFICE,a312bdeb-1e21-40d0-84b1-0e73f128144f,Defender Platform for Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCHANGE_S_ENTERPRISE,efb87545-963c-4e0d-99df-69c6916d9eb0,Exchange Online (Plan 2) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,GRAPH_CONNECTORS_SEARCH_INDEX,a6520331-d7d4-4276-95f5-15c0933bc757,Graph Connectors Search with Index +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Content_Explorer,d9fa6af4-e046-4c89-9226-729a0786685d,Information Protection and Governance Analytics - Premium +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ContentExplorer_Standard,2b815d45-56e4-4e3a-b65c-66cb9175b560,Information Protection and Governance Analytics – Standard +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_CLP2,efb0351d-3b08-4503-993d-383af8de41e3,Information Protection for Office 365 - Premium +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_CLP1,5136a095-5cf0-4aff-bec3-e84448b38ea5,Information Protection for Office 365 - Standard +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,M365_ADVANCED_AUDITING,2f442157-a11c-46b9-ae5b-6e39ff4e5849,Microsoft 365 Advanced Auditing +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,OFFICESUBSCRIPTION,43de0ff5-c92c-492b-9116-175376d08c38,Microsoft 365 Apps for enterprise +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,M365_AUDIT_PLATFORM,f6de4823-28fa-440b-b886-4783fa86ddba,Microsoft 365 Audit Platform +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_COMMUNICATION_COMPLIANCE,a413a9ff-720c-4822-98ef-2f37c2a21f4c,Microsoft 365 Communication Compliance +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MTP,bf28f719-7844-4079-9c78-c1307898e192,Microsoft 365 Defender +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFTBOOKINGS,199a5c09-e0ca-4e37-8f7c-b05d533e1ea2,Microsoft Bookings +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CLIPCHAMP,a1ace008-72f3-4ea0-8dac-33b3a23a2472,Microsoft Clipchamp +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMUNICATIONS_DLP,6dc145d6-95dd-4191-b9c3-185575ee6f6b,Microsoft Communications DLP +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CUSTOMER_KEY,6db1f1db-2b46-403f-be40-e39395f08dbb,Microsoft Customer Key +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ATP_ENTERPRISE,f20fedf3-f3c3-43c3-8267-2bfdd51c0939,Microsoft Defender for Office 365 (Plan 1) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,THREAT_INTELLIGENCE,8e0c0a52-6a6c-4d40-8370-dd62790dcd70,Microsoft Defender for Office 365 (Plan 2) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCEL_PREMIUM,531ee2f8-b1cb-453b-9c21-d2180d014ca5,Microsoft Excel Advanced Analytics +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,OFFICE_FORMS_PLAN_3,96c1e14a-ef43-418d-b115-9636cdaa8eed,Microsoft Forms (Plan 3) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INFO_GOVERNANCE,e26c2fcc-ab91-4a61-b35c-03cdc8dddf66,Microsoft Information Governance +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INSIDER_RISK,d587c7a3-bda9-4f99-8776-9bcf59c84f75,Microsoft Insider Risk Management +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INSIDER_RISK_MANAGEMENT,9d0c4ee5-e4a1-4625-ab39-d82b619b1a34,Microsoft Insider Risk Management - Exchange +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,KAIZALA_STANDALONE,0898bdbb-73b0-471a-81e5-20f1fe4dd66e,Microsoft Kaizala Pro +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_LOOP,c4b8c31a-fb44-4c65-9837-a21f55fcabda,Microsoft Loop +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ML_CLASSIFICATION,d2d51368-76c9-4317-ada2-a12c004c432f,Microsoft ML-Based Classification +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCHANGE_ANALYTICS,34c0d7a0-a70f-4668-9238-47f9fc208882,Microsoft MyAnalytics (Full) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RECORDS_MANAGEMENT,65cc641f-cccd-4643-97e0-a17e3045e541,Microsoft Records Management +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_SEARCH,94065c59-bc8e-4e8b-89e5-5138d471eaff,Microsoft Search +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Deskless,8c7d2df8-86f0-4902-b2ed-a0458298f3b3,Microsoft StaffHub +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,STREAM_O365_E5,6c6042f5-6f01-4d67-b8c1-eb99d36eed3e,Microsoft Stream for Office 365 E5 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,TEAMS1,57ff2da0-773e-42df-b2af-ffb7a2317929,Microsoft Teams +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MINECRAFT_EDUCATION_EDITION,4c246bbc-f513-4311-beff-eba54c353256,Minecraft Education Edition +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_O365,882e1d05-acd1-4ccb-8708-6ee03664b117,Mobile Device Management for Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Nucleus,db4d623d-b514-490b-b7ef-8885eee514de,Nucleus +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EQUIVIO_ANALYTICS,4de31727-a228-4ec3-a5bf-8e45b5ca48cc,Office 365 Advanced eDiscovery +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ADALLOM_S_O365,8c098270-9dd4-4350-9b30-ba4703f3b36b,Office 365 Cloud App Security +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PAM_ENTERPRISE,b1188c4c-1b36-4018-b48b-ee07604f6feb,Office 365 Privileged Access Management +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SAFEDOCS,bf6f5520-59e3-4f82-974b-7dbbc4fd27c7,Office 365 SafeDocs +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SHAREPOINTWAC_EDU,e03c7e47-402c-463c-ab25-949079bedb21,Office for the Web for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,POWERAPPS_O365_P3,9c0dab89-a30c-4117-86e7-97bda240acd2,Power Apps for Office 365 (Plan 3) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,BI_AZURE_P2,70d33638-9c74-4d01-bfd3-562de28bd4ba,Power BI Pro +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PREMIUM_ENCRYPTION,617b097b-4b93-4ede-83de-5f075bb5fb2f,Premium Encryption in Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PROJECT_O365_P3,b21a6b06-1988-436e-a07b-51ec6d9f52ad,Project for Office (Plan E5) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PURVIEW_DISCOVERY,c948ea65-2053-4a5a-8a62-9eaaaf11b522,Purview Discovery +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Bing_Chat_Enterprise,0d0c0d31-fae7-41f2-b909-eaf4d7f26dba,RETIRED - Commercial data protection for Microsoft Copilot +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMUNICATIONS_COMPLIANCE,41fcdd7d-4733-4863-9cf4-c65b83ce2df4,RETIRED - Microsoft Communications Compliance +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,DATA_INVESTIGATIONS,46129a58-a698-46f0-aa5b-17f6586297d9,Retired - Microsoft Data Investigations +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SCHOOL_DATA_SYNC_P2,500b6a2a-7a50-4f40-b5f9-160e5b8c2f48,School Data Sync (Plan 2) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SHAREPOINTENTERPRISE_EDU,63038b2c-28d0-45f6-bc36-33062963b498,SharePoint (Plan 2) for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SWAY,a23b959c-7ce8-4e57-9140-b90eb88a9e97,Sway +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,BPOS_S_TODO_3,3fb82609-8c27-4f7b-bd51-30634711ee67,To-Do (Plan 3) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,VIVA_LEARNING_SEEDED,b76fb638-6ba6-402a-b9f9-83d28acb3d86,Viva Learning Seeded +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WHITEBOARD_PLAN3,4a51bca5-1eff-43f5-878c-177680f191af,Whiteboard (Plan 3) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WINDEFATP,871d91ec-ec1a-452b-a83f-bd76c7d770ef,Microsoft Defender for Endpoint +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFTENDPOINTDLP,64bfac92-2b17-4482-b5e5-a0304429de3e,Microsoft Endpoint DLP +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,UNIVERSAL_PRINT_01,795f6fe0-cc4d-4773-b050-5dde4dc704c9,Universal Print +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Virtualization Rights for Windows 10 (E3/E5+VDA),e7c91390-7625-45be-94e0-e16907e03118,Windows 10/11 Enterprise +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WINDOWSUPDATEFORBUSINESS_DEPLOYMENTSERVICE,7bf960f6-2cd9-443a-8046-5dbff9558365,Windows Update for Business Deployment Service +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_PREMIUM,6c57d4b6-3b23-47a5-9bc9-69f17b4947b3,Azure Information Protection Premium P1 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_PREMIUM2,5689bec4-755d-4753-8b61-40975025187c,Azure Information Protection Premium P2 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,DYN365_CDS_O365_P3,28b0fa46-c39a-4188-89e2-58e979a6b014,Common Data Service +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Intune_ServiceNow,3eeb8536-fecf-41bf-a3f8-d6f17a9f3efc,Intune ServiceNow Integration +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MFA_PREMIUM,8a256a2b-b617-496d-b51b-e76466e88db0,Microsoft Azure Multi-Factor Authentication +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ADALLOM_S_STANDALONE,2e2ddb96-6af9-4b1d-a3f0-d6ecfd22edb2,Microsoft Defender for Cloud Apps +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ATA,14ab5db5-e6c4-4b20-b4bc-13e36fd2227f,Microsoft Defender for Identity +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_PREMIUM_P2,eec0eb4f-6444-4f95-aba0-50c24d67f998,Microsoft Entra ID P2 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune Plan 1 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune Plan 1 for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,FLOW_O365_P3,07699545-9485-468e-95b6-2fca3738be01,Power Automate for Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,POWER_VIRTUAL_AGENTS_O365_P3,ded3d325-1bdc-453e-8432-5bac26d7a014,Power Virtual Agents for Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,REMOTE_HELP,a4c6cf29-1168-4076-ba5c-e8fe0e62b17e,Remote help +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,CDS_O365_P3,afa73018-811e-46e9-988f-f75d2b1b8430,Common Data Service for Teams Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,LOCKBOX_ENTERPRISE,9f431833-0334-42de-a7dc-70aa40db46db,Customer Lockbox +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,CustomerLockboxA_Enterprise,3ec18638-bd4c-4d3b-8905-479ed636b83e,Customer Lockbox (A) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MIP_S_Exchange,cd31b152-6326-4d1b-ae1b-997b625182e6,Data Classification in Microsoft 365 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,COMMON_DEFENDER_PLATFORM_FOR_OFFICE,a312bdeb-1e21-40d0-84b1-0e73f128144f,Defender Platform for Office 365 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,EXCHANGE_S_ENTERPRISE,efb87545-963c-4e0d-99df-69c6916d9eb0,Exchange Online (Plan 2) +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,GRAPH_CONNECTORS_SEARCH_INDEX,a6520331-d7d4-4276-95f5-15c0933bc757,Graph Connectors Search with Index Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,Content_Explorer,d9fa6af4-e046-4c89-9226-729a0786685d,Information Protection and Governance Analytics - Premium Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ContentExplorer_Standard,2b815d45-56e4-4e3a-b65c-66cb9175b560,Information Protection and Governance Analytics – Standard Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MIP_S_CLP2,efb0351d-3b08-4503-993d-383af8de41e3,Information Protection for Office 365 - Premium Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MIP_S_CLP1,5136a095-5cf0-4aff-bec3-e84448b38ea5,Information Protection for Office 365 - Standard Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,M365_ADVANCED_AUDITING,2f442157-a11c-46b9-ae5b-6e39ff4e5849,Microsoft 365 Advanced Auditing -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,OFFICESUBSCRIPTION,43de0ff5-c92c-492b-9116-175376d08c38,Microsoft 365 Apps for Enterprise +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,OFFICESUBSCRIPTION,43de0ff5-c92c-492b-9116-175376d08c38,Microsoft 365 Apps for enterprise Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,M365_AUDIT_PLATFORM,f6de4823-28fa-440b-b886-4783fa86ddba,Microsoft 365 Audit Platform Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MICROSOFT_COMMUNICATION_COMPLIANCE,a413a9ff-720c-4822-98ef-2f37c2a21f4c,Microsoft 365 Communication Compliance Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MTP,bf28f719-7844-4079-9c78-c1307898e192,Microsoft 365 Defender +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MICROSOFTBOOKINGS,199a5c09-e0ca-4e37-8f7c-b05d533e1ea2,Microsoft Bookings +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,CLIPCHAMP,a1ace008-72f3-4ea0-8dac-33b3a23a2472,Microsoft Clipchamp Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,COMMUNICATIONS_DLP,6dc145d6-95dd-4191-b9c3-185575ee6f6b,Microsoft Communications DLP Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,CUSTOMER_KEY,6db1f1db-2b46-403f-be40-e39395f08dbb,Microsoft Customer Key -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,DATA_INVESTIGATIONS,46129a58-a698-46f0-aa5b-17f6586297d9,Microsoft Data Investigations Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ATP_ENTERPRISE,f20fedf3-f3c3-43c3-8267-2bfdd51c0939,Microsoft Defender for Office 365 (Plan 1) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,THREAT_INTELLIGENCE,8e0c0a52-6a6c-4d40-8370-dd62790dcd70,Microsoft Defender for Office 365 (Plan 2) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,EXCEL_PREMIUM,531ee2f8-b1cb-453b-9c21-d2180d014ca5,Microsoft Excel Advanced Analytics Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,OFFICE_FORMS_PLAN_3,96c1e14a-ef43-418d-b115-9636cdaa8eed,Microsoft Forms (Plan 3) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INFO_GOVERNANCE,e26c2fcc-ab91-4a61-b35c-03cdc8dddf66,Microsoft Information Governance Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INSIDER_RISK,d587c7a3-bda9-4f99-8776-9bcf59c84f75,Microsoft Insider Risk Management +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INSIDER_RISK_MANAGEMENT,9d0c4ee5-e4a1-4625-ab39-d82b619b1a34,Microsoft Insider Risk Management - Exchange Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,KAIZALA_STANDALONE,0898bdbb-73b0-471a-81e5-20f1fe4dd66e,Microsoft Kaizala Pro +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MICROSOFT_LOOP,c4b8c31a-fb44-4c65-9837-a21f55fcabda,Microsoft Loop Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ML_CLASSIFICATION,d2d51368-76c9-4317-ada2-a12c004c432f,Microsoft ML-Based Classification Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,EXCHANGE_ANALYTICS,34c0d7a0-a70f-4668-9238-47f9fc208882,Microsoft MyAnalytics (Full) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner @@ -1091,8 +1117,10 @@ Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,BI_AZURE_P2,70d33638-9c74-4d01-bfd3-562de28bd4ba,Power BI Pro Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,PREMIUM_ENCRYPTION,617b097b-4b93-4ede-83de-5f075bb5fb2f,Premium Encryption in Office 365 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,PROJECT_O365_P3,b21a6b06-1988-436e-a07b-51ec6d9f52ad,Project for Office (Plan E5) +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,PURVIEW_DISCOVERY,c948ea65-2053-4a5a-8a62-9eaaaf11b522,Purview Discovery +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,Bing_Chat_Enterprise,0d0c0d31-fae7-41f2-b909-eaf4d7f26dba,RETIRED - Commercial data protection for Microsoft Copilot Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,COMMUNICATIONS_COMPLIANCE,41fcdd7d-4733-4863-9cf4-c65b83ce2df4,RETIRED - Microsoft Communications Compliance -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INSIDER_RISK_MANAGEMENT,9d0c4ee5-e4a1-4625-ab39-d82b619b1a34,RETIRED - Microsoft Insider Risk Management +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,DATA_INVESTIGATIONS,46129a58-a698-46f0-aa5b-17f6586297d9,Retired - Microsoft Data Investigations Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,SCHOOL_DATA_SYNC_P2,500b6a2a-7a50-4f40-b5f9-160e5b8c2f48,School Data Sync (Plan 2) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,SHAREPOINTENTERPRISE_EDU,63038b2c-28d0-45f6-bc36-33062963b498,SharePoint (Plan 2) for Education Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) @@ -1105,18 +1133,20 @@ Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,UNIVERSAL_PRINT_01,795f6fe0-cc4d-4773-b050-5dde4dc704c9,Universal Print Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,Virtualization Rights for Windows 10 (E3/E5+VDA),e7c91390-7625-45be-94e0-e16907e03118,Windows 10/11 Enterprise Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,WINDOWSUPDATEFORBUSINESS_DEPLOYMENTSERVICE,7bf960f6-2cd9-443a-8046-5dbff9558365,Windows Update for Business Deployment Service -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_PREMIUM_P2,eec0eb4f-6444-4f95-aba0-50c24d67f998,Microsoft Entra ID P2 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,RMS_S_PREMIUM,6c57d4b6-3b23-47a5-9bc9-69f17b4947b3,Azure Information Protection Premium P1 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,RMS_S_PREMIUM2,5689bec4-755d-4753-8b61-40975025187c,Azure Information Protection Premium P2 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,DYN365_CDS_O365_P3,28b0fa46-c39a-4188-89e2-58e979a6b014,Common Data Service +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,Intune_ServiceNow,3eeb8536-fecf-41bf-a3f8-d6f17a9f3efc,Intune ServiceNow Integration Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MFA_PREMIUM,8a256a2b-b617-496d-b51b-e76466e88db0,Microsoft Azure Multi-Factor Authentication Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ADALLOM_S_STANDALONE,2e2ddb96-6af9-4b1d-a3f0-d6ecfd22edb2,Microsoft Defender for Cloud Apps Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ATA,14ab5db5-e6c4-4b20-b4bc-13e36fd2227f,Microsoft Defender for Identity -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune for Education +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_PREMIUM_P2,eec0eb4f-6444-4f95-aba0-50c24d67f998,Microsoft Entra ID P2 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune Plan 1 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune Plan 1 for Education Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,FLOW_O365_P3,07699545-9485-468e-95b6-2fca3738be01,Power Automate for Office 365 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,POWER_VIRTUAL_AGENTS_O365_P3,ded3d325-1bdc-453e-8432-5bac26d7a014,Power Virtual Agents for Office 365 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,REMOTE_HELP,a4c6cf29-1168-4076-ba5c-e8fe0e62b17e,Remote help Microsoft 365 A5 for students use benefit,M365EDU_A5_STUUSEBNFT,31d57bc7-3a05-4867-ab53-97a17835a411,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education Microsoft 365 A5 for students use benefit,M365EDU_A5_STUUSEBNFT,31d57bc7-3a05-4867-ab53-97a17835a411,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management Microsoft 365 A5 for students use benefit,M365EDU_A5_STUUSEBNFT,31d57bc7-3a05-4867-ab53-97a17835a411,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics @@ -3633,13 +3663,19 @@ Microsoft Dynamics CRM Online,CRMSTANDARD,d17b27af-3f49-4822-99f9-56a661538792,M Microsoft Dynamics CRM Online,CRMSTANDARD,d17b27af-3f49-4822-99f9-56a661538792,NBPROFESSIONALFORCRM,3e58e97c-9abe-ebab-cd5f-d543d1529634,MICROSOFT SOCIAL ENGAGEMENT PROFESSIONAL - ELIGIBILITY CRITERIA APPLY Microsoft Dynamics CRM Online,CRMSTANDARD,d17b27af-3f49-4822-99f9-56a661538792,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,POWERAPPS FOR DYNAMICS 365 Microsoft Entra ID Governance,Microsoft_Entra_ID_Governance,cf6b0d46-4093-4546-a0ab-0b1546dcc10e,Entra_Identity_Governance,e866a266-3cff-43a3-acca-0c90a7e00c8b,Entra Identity Governance +Microsoft Entra Suite Add-on for Microsoft Entra ID P2,Microsoft_Entra_Suite_Step_Up_for_Microsoft_Entra_ID_P2,2ef3064c-c95c-426c-96dd-9ffeaa2f2c37,Entra_Premium_Internet_Access,8d23cb83-ab07-418f-8517-d7aca77307dc,Microsoft Entra Internet Access +Microsoft Entra Suite Add-on for Microsoft Entra ID P2,Microsoft_Entra_Suite_Step_Up_for_Microsoft_Entra_ID_P2,2ef3064c-c95c-426c-96dd-9ffeaa2f2c37,Entra_Premium_Private_Access,f057aab1-b184-49b2-85c0-881b02a405c5,Microsoft Entra Private Access +Microsoft Entra Suite Add-on for Microsoft Entra ID P2,Microsoft_Entra_Suite_Step_Up_for_Microsoft_Entra_ID_P2,2ef3064c-c95c-426c-96dd-9ffeaa2f2c37,Verifiable_Credentials_Service_Request,aae826b7-14cd-4691-8178-2b312f7072ea,Verifiable Credentials Service Request +Microsoft Entra Suite Add-on for Microsoft Entra ID P2,Microsoft_Entra_Suite_Step_Up_for_Microsoft_Entra_ID_P2,2ef3064c-c95c-426c-96dd-9ffeaa2f2c37,Entra_Identity_Governance,e866a266-3cff-43a3-acca-0c90a7e00c8b,Entra Identity Governance Microsoft Fabric (Free),POWER_BI_STANDARD,a403ebcc-fae0-4ca2-8c8c-7a907fd6c235,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Microsoft Fabric (Free),POWER_BI_STANDARD,a403ebcc-fae0-4ca2-8c8c-7a907fd6c235,BI_AZURE_P0,2049e525-b859-401b-b2a0-e0a31c4b1fe4,Power BI (free) +Microsoft Fabric (Free),POWER_BI_STANDARD,a403ebcc-fae0-4ca2-8c8c-7a907fd6c235,PURVIEW_DISCOVERY,c948ea65-2053-4a5a-8a62-9eaaaf11b522,Purview Discovery Microsoft Fabric (Free) for faculty,POWER_BI_STANDARD_FACULTY,ade29b5f-397e-4eb9-a287-0344bd46c68d,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,EXCHANGE_S_FOUNDATION Microsoft Fabric (Free) for faculty,POWER_BI_STANDARD_FACULTY,ade29b5f-397e-4eb9-a287-0344bd46c68d,BI_AZURE_P0,2049e525-b859-401b-b2a0-e0a31c4b1fe4,BI_AZURE_P0 Microsoft Fabric (Free) for student,POWER_BI_STANDARD_STUDENT,bdcaf6aa-04c1-4b8f-b64e-6e3bd505ac64,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,EXCHANGE_S_FOUNDATION Microsoft Fabric (Free) for student,POWER_BI_STANDARD_STUDENT,bdcaf6aa-04c1-4b8f-b64e-6e3bd505ac64,BI_AZURE_P0,2049e525-b859-401b-b2a0-e0a31c4b1fe4,BI_AZURE_P0 Microsoft Imagine Academy,IT_ACADEMY_AD,ba9a34de-4489-469d-879c-0f0f145321cd,IT_ACADEMY_AD,d736def0-1fde-43f0-a5be-e3f8b2de6e41,MS IMAGINE ACADEMY +Microsoft Intune Advanced Analytics,Microsoft_Intune_Advanced_Analytics,5e36d0d4-e9e5-4052-aba0-0257465c9b86,Intune_AdvancedEA,2a4baa0e-5e99-4c38-b1f2-6864960f1bd1,Microsoft Intune Advanced Analytics Microsoft Intune Device,INTUNE_A_D,2b317a4a-77a6-4188-9437-b68a77b4e2c6,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Microsoft Intune Device,INTUNE_A_D,2b317a4a-77a6-4188-9437-b68a77b4e2c6,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune Microsoft Intune Device for Government,INTUNE_A_D_GOV,2c21e77a-e0d6-4570-b38a-7ff2dc17d2ca,EXCHANGE_S_FOUNDATION_GOV,922ba911-5694-4e99-a794-73aed9bfeec8,Exchange Foundation for Government @@ -3696,6 +3732,10 @@ Microsoft Stream Storage Add-On (500 GB),STREAM_STORAGE,9bd7c846-9556-4453-a542- Microsoft Sustainability Manager Premium,Microsoft_Sustainability_Manager_Premium,aecb477b-2f56-4e38-b711-b752c24fc19b,CDS_CLOUD_FOR_SUSTAINABILITY_PLUS,ba80223c-e515-4642-a838-3e7d66f70cb6,Common Data Services for Cloud for Sustainability Plus Microsoft Sustainability Manager Premium,Microsoft_Sustainability_Manager_Premium,aecb477b-2f56-4e38-b711-b752c24fc19b,MCS_BIZAPPS_CLOUD_FOR_SUSTAINABILITY_PLUS,ed29ae92-ff5f-4446-8460-83c54d0e7088,MCS - BizApps Cloud for Sustainability Plus Microsoft Sustainability Manager Premium,Microsoft_Sustainability_Manager_Premium,aecb477b-2f56-4e38-b711-b752c24fc19b,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +Microsoft Sustainability Manager Premium USL Plus,MICROSOFT_SUSTAINABILITY_MANAGER_PREMIUM_USL_ADDON,9d576ffb-dd32-4c33-91ee-91625b61424a,MCS_BIZAPPS_CLOUD_FOR_SUSTAINABILITY_USL_PLUS,beaf5b5c-d11c-4417-b5cb-cd9f9e6719b0,MCS - BizApps Cloud for Sustainability USL Plus +Microsoft Sustainability Manager Premium USL Plus,MICROSOFT_SUSTAINABILITY_MANAGER_PREMIUM_USL_ADDON,9d576ffb-dd32-4c33-91ee-91625b61424a,POWER_APPS_FOR_MCS_USL_PLUS,c5502fe7-406d-442a-827f-4948b821ba08,Power Apps for Cloud for Sustainability USL Plus +Microsoft Sustainability Manager Premium USL Plus,MICROSOFT_SUSTAINABILITY_MANAGER_PREMIUM_USL_ADDON,9d576ffb-dd32-4c33-91ee-91625b61424a,POWER_AUTOMATE_FOR_MCS_USL_PLUS,1c22bb50-96fb-49e5-baa6-195cab19eee2,Power Automate for Cloud for Sustainability USL Plus +Microsoft Sustainability Manager Premium USL Plus,MICROSOFT_SUSTAINABILITY_MANAGER_PREMIUM_USL_ADDON,9d576ffb-dd32-4c33-91ee-91625b61424a,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Microsoft Sustainability Manager USL Essentials,Microsoft_Cloud_for_Sustainability_USL,ece037b4-a52b-4cf8-93ea-649e5d83767a,MCS_BizApps_Cloud_for_Sustainability_USL,c46c42af-d654-4385-8c85-29a84f3dfb22,MCS - BizApps - Cloud for Sustainability USL Microsoft Sustainability Manager USL Essentials,Microsoft_Cloud_for_Sustainability_USL,ece037b4-a52b-4cf8-93ea-649e5d83767a,POWER_APPS_FOR_MCS_USL,5ffd371c-037a-41a2-98a3-6452f8c5de17,Power Apps for Cloud for Sustainability USL Microsoft Sustainability Manager USL Essentials,Microsoft_Cloud_for_Sustainability_USL,ece037b4-a52b-4cf8-93ea-649e5d83767a,POWER_AUTOMATE_FOR_MCS_USL,ccbe468e-7973-442c-8ec4-5fbe16438711,Power Automate for Cloud for Sustainability USL @@ -3808,18 +3848,20 @@ Microsoft Teams Rooms Pro,Microsoft_Teams_Rooms_Pro,4cde982a-ede4-4409-9ae6-b003 Microsoft Teams Rooms Pro,Microsoft_Teams_Rooms_Pro,4cde982a-ede4-4409-9ae6-b003453c8ea6,TEAMS1,57ff2da0-773e-42df-b2af-ffb7a2317929,Microsoft Teams Microsoft Teams Rooms Pro,Microsoft_Teams_Rooms_Pro,4cde982a-ede4-4409-9ae6-b003453c8ea6,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) Microsoft Teams Rooms Pro,Microsoft_Teams_Rooms_Pro,4cde982a-ede4-4409-9ae6-b003453c8ea6,WHITEBOARD_PLAN3,4a51bca5-1eff-43f5-878c-177680f191af,Whiteboard (Plan 3) -Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education +Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,TEAMS1,57ff2da0-773e-42df-b2af-ffb7a2317929,Microsoft Teams Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,MTRProManagement,ecc74eae-eeb7-4ad5-9c88-e8b2bfca75b8,Microsoft Teams Rooms Pro Management Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) +Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,Teams_Rooms_Pro,0374d34c-6be4-4dbb-b3f0-26105db0b28a,Teams Rooms Pro Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,Teams_Room_Basic,8081ca9c-188c-4b49-a8e5-c23b5e9463a8,Teams Rooms Test 1 Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,Teams_Room_Pro,ec17f317-f4bc-451e-b2da-0167e5c260f9,Teams Rooms Test 2 Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,WHITEBOARD_PLAN3,4a51bca5-1eff-43f5-878c-177680f191af,Whiteboard (Plan 3) Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,WINDEFATP,871d91ec-ec1a-452b-a83f-bd76c7d770ef,Microsoft Defender for Endpoint Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune Plan 1 +Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,SPECIALTY_DEVICES,cfce7ae3-4b41-4438-999c-c0e91f3b7fb9,Specialty devices Microsoft Teams Rooms Pro for GCC,Microsoft_Teams_Rooms_Pro_GCC,31ecb341-2a17-483e-9140-c473006d1e1a,MCOMEETADV_GOV,f544b08d-1645-4287-82de-8d91f37c02a1,Microsoft 365 Audio Conferencing for Government Microsoft Teams Rooms Pro for GCC,Microsoft_Teams_Rooms_Pro_GCC,31ecb341-2a17-483e-9140-c473006d1e1a,MCOEV_GOV,db23fce2-a974-42ef-9002-d78dd42a0f22,Microsoft 365 Phone System for Government Microsoft Teams Rooms Pro for GCC,Microsoft_Teams_Rooms_Pro_GCC,31ecb341-2a17-483e-9140-c473006d1e1a,TEAMS_GOV,304767db-7d23-49e8-a945-4a7eb65f9f28,Microsoft Teams for Government @@ -3914,14 +3956,14 @@ Office 365 Multi-Geo Capabilities,OFFICE365_MULTIGEO,84951599-62b7-46f3-9c9d-305 Office 365 Multi-Geo Capabilities,OFFICE365_MULTIGEO,84951599-62b7-46f3-9c9d-30551b2ad607,TEAMSMULTIGEO,41eda15d-6b52-453b-906f-bc4a5b25a26b,Teams Multi-Geo Nonprofit Portal,NONPROFIT_PORTAL,aa2695c9-8d59-4800-9dc8-12e01f1735af,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Nonprofit Portal,NONPROFIT_PORTAL,aa2695c9-8d59-4800-9dc8-12e01f1735af,NONPROFIT_PORTAL,7dbc2d88-20e2-4eb6-b065-4510b38d6eb2,Nonprofit Portal -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service - O365 P1 +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,EXCHANGE_S_STANDARD,9aaf7827-d63c-4b61-89c3-182f06f82e5c,Exchange Online (Plan 1) Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Microsoft Microsoft Entra Rights +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,OFFICE_FORMS_PLAN_2,9b5de886-f035-4ff2-b3d8-c9127bea3620,Microsoft Forms (Plan 2) -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,KAIZALA_O365_P2,54fc630f-5a40-48ee-8965-af0503c1386e,Microsoft Kaizala Pro Plan 2 +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,KAIZALA_O365_P2,54fc630f-5a40-48ee-8965-af0503c1386e,Microsoft Kaizala Pro Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,MICROSOFT_SEARCH,94065c59-bc8e-4e8b-89e5-5138d471eaff,Microsoft Search Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,Deskless,8c7d2df8-86f0-4902-b2ed-a0458298f3b3,Microsoft StaffHub @@ -3931,9 +3973,8 @@ Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c897 Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,Nucleus,db4d623d-b514-490b-b7ef-8885eee514de,Nucleus Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,SHAREPOINTWAC_EDU,e03c7e47-402c-463c-ab25-949079bedb21,Office for the Web for Education Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,OFFICEMOBILE_SUBSCRIPTION,c63d4d19-e8cb-460e-b37c-4d6c34603745,Office Mobile Apps for Office 365 -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,PROJECT_O365_P1,a55dfd10-0864-46d9-a3cd-da5991a3e0e2,Project for Office (Plan E1) +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,Bing_Chat_Enterprise,0d0c0d31-fae7-41f2-b909-eaf4d7f26dba,RETIRED - Commercial data protection for Microsoft Copilot Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,SCHOOL_DATA_SYNC_P1,c33802dd-1b50-4b9a-8bb9-f13d2cdeadac,School Data Sync (Plan 1) Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,SHAREPOINTSTANDARD_EDU,0a4983bb-d3e5-4a09-95d8-b2d0127b3df5,SharePoint (Plan 1) for Education Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) @@ -3942,6 +3983,9 @@ Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c897 Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,VIVA_LEARNING_SEEDED,b76fb638-6ba6-402a-b9f9-83d28acb3d86,Viva Learning Seeded Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,WHITEBOARD_PLAN1,b8afc642-032e-4de5-8c0a-507a7bba7e5d,Whiteboard (Plan 1) Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service - O365 P1 Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics @@ -3969,14 +4013,14 @@ Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-89 Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,VIVA_LEARNING_SEEDED,b76fb638-6ba6-402a-b9f9-83d28acb3d86,Viva Learning Seeded Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,WHITEBOARD_PLAN1,b8afc642-032e-4de5-8c0a-507a7bba7e5d,Whiteboard (Plan 1) Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service - O365 P1 +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,EXCHANGE_S_STANDARD,9aaf7827-d63c-4b61-89c3-182f06f82e5c,Exchange Online (Plan 1) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Microsoft Microsoft Entra Rights +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,OFFICE_FORMS_PLAN_2,9b5de886-f035-4ff2-b3d8-c9127bea3620,Microsoft Forms (Plan 2) -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,KAIZALA_O365_P2,54fc630f-5a40-48ee-8965-af0503c1386e,Microsoft Kaizala Pro Plan 2 +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,KAIZALA_O365_P2,54fc630f-5a40-48ee-8965-af0503c1386e,Microsoft Kaizala Pro Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,MICROSOFT_SEARCH,94065c59-bc8e-4e8b-89e5-5138d471eaff,Microsoft Search Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,Deskless,8c7d2df8-86f0-4902-b2ed-a0458298f3b3,Microsoft StaffHub @@ -3985,9 +4029,8 @@ Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4 Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,INTUNE_O365,882e1d05-acd1-4ccb-8708-6ee03664b117,Mobile Device Management for Office 365 Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,SHAREPOINTWAC_EDU,e03c7e47-402c-463c-ab25-949079bedb21,Office for the Web for Education Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,OFFICEMOBILE_SUBSCRIPTION,c63d4d19-e8cb-460e-b37c-4d6c34603745,Office Mobile Apps for Office 365 -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,PROJECT_O365_P1,a55dfd10-0864-46d9-a3cd-da5991a3e0e2,Project for Office (Plan E1) +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,Bing_Chat_Enterprise,0d0c0d31-fae7-41f2-b909-eaf4d7f26dba,RETIRED - Commercial data protection for Microsoft Copilot Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,SCHOOL_DATA_SYNC_P1,c33802dd-1b50-4b9a-8bb9-f13d2cdeadac,School Data Sync (Plan 1) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,SHAREPOINTSTANDARD_EDU,0a4983bb-d3e5-4a09-95d8-b2d0127b3df5,SharePoint (Plan 1) for Education Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) @@ -3995,6 +4038,9 @@ Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4 Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,BPOS_S_TODO_2,c87f142c-d1e9-4363-8630-aaea9c4d9ae5,To-Do (Plan 2) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,WHITEBOARD_PLAN1,b8afc642-032e-4de5-8c0a-507a7bba7e5d,Whiteboard (Plan 1) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 Office 365 A1 Plus for students,STANDARDWOFFPACK_IW_STUDENT,e82ae690-a2d5-4d76-8d30-7c6e01e6022e,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education Office 365 A1 Plus for students,STANDARDWOFFPACK_IW_STUDENT,e82ae690-a2d5-4d76-8d30-7c6e01e6022e,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service - O365 P1 Office 365 A1 Plus for students,STANDARDWOFFPACK_IW_STUDENT,e82ae690-a2d5-4d76-8d30-7c6e01e6022e,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics @@ -5059,8 +5105,11 @@ Power Apps Per User BD Only,POWERAPPS_PER_USER_BD_ONLY,2ced8a00-3ed1-4295-ab7c-5 Power Apps Per User BD Only,POWERAPPS_PER_USER_BD_ONLY,2ced8a00-3ed1-4295-ab7c-57170ff28e58,CDS_ POWERAPPS_PER_USER_CUSTOM,2e8dde43-6986-479d-b179-7dbe31c31f60,CDS Power Apps Per User Custom Power Apps Per User BD Only,POWERAPPS_PER_USER_BD_ONLY,2ced8a00-3ed1-4295-ab7c-57170ff28e58,POWERAPPS_PER_USER,ea2cf03b-ac60-46ae-9c1d-eeaeb63cec86,Power Apps per User Plan Power Apps Per User BD Only,POWERAPPS_PER_USER_BD_ONLY,2ced8a00-3ed1-4295-ab7c-57170ff28e58,Flow_PowerApps_PerUser,dc789ed8-0170-4b65-a415-eb77d5bb350a,Power Automate for Power Apps per User Plan -Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,DYN365_CDS_P2,6ea4c1ef-c259-46df-bce2-943342cd3cb2,Common Data Service - P2 +Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,CDSAICAPACITY_PERUSER_NEW,74d93933-6f22-436e-9441-66d205435abb,AI Builder capacity Per User add-on +Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,DYN365_CDS_P2,6ea4c1ef-c259-46df-bce2-943342cd3cb2,Common Data Service +Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,CDSAICAPACITY_PERUSER,91f50f7b-2204-4803-acac-5cf5668b8b39,DO NOT USE - AI Builder capacity Per User add-on Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,POWERAPPS_PER_USER,ea2cf03b-ac60-46ae-9c1d-eeaeb63cec86,Power Apps per User Plan Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,Flow_PowerApps_PerUser,dc789ed8-0170-4b65-a415-eb77d5bb350a,Power Automate for Power Apps per User Plan Power Apps Premium for Government,POWERAPPS_PER_USER_GCC,8e4c6baa-f2ff-4884-9c38-93785d0d7ba1,CDSAICAPACITY_PERUSER,91f50f7b-2204-4803-acac-5cf5668b8b39,AI Builder capacity Per User add-on @@ -5130,6 +5179,8 @@ Power BI Premium Per User,PBI_PREMIUM_PER_USER,c1d032e0-5619-4761-9b5c-75b6831e1 Power BI Premium Per User,PBI_PREMIUM_PER_USER,c1d032e0-5619-4761-9b5c-75b6831e1711,BI_AZURE_P3,0bf3c642-7bb5-4ccc-884e-59d09df0266c,Power BI Premium Per User Power BI Premium Per User,PBI_PREMIUM_PER_USER,c1d032e0-5619-4761-9b5c-75b6831e1711,BI_AZURE_P2,70d33638-9c74-4d01-bfd3-562de28bd4ba,Power BI Pro Power BI Premium Per User Add-On,PBI_PREMIUM_PER_USER_ADDON,de376a03-6e5b-42ec-855f-093fb50b8ca5,BI_AZURE_P3,0bf3c642-7bb5-4ccc-884e-59d09df0266c,Power BI Premium Per User +Power BI Premium Per User Add-On for Faculty,PBI_PREMIUM_PER_USER_ADDON_FACULTY,c05b235f-be75-4029-8851-6a4170758eef,BI_AZURE_P3,0bf3c642-7bb5-4ccc-884e-59d09df0266c,Power BI Premium Per User +Power BI Premium Per User Add-On for Faculty,PBI_PREMIUM_PER_USER_ADDON_FACULTY,c05b235f-be75-4029-8851-6a4170758eef,PURVIEW_DISCOVERY,c948ea65-2053-4a5a-8a62-9eaaaf11b522,Purview Discovery Power BI Premium Per User Add-On for GCC,PBI_PREMIUM_PER_USER_ADDON_CE_GCC,66024bbf-4cd4-4329-95c8-c932e2ae01a8,BI_AZURE_P3_GOV,32d15238-9a8c-46da-af3f-21fc5351d365,Power BI Premium Per User for Government Power BI Premium Per User Add-On for GCC,PBI_PREMIUM_PER_USER_ADDON_GCC,1b572d5e-1bf8-4b19-9259-f9eda31a6972,BI_AZURE_P3_GOV,32d15238-9a8c-46da-af3f-21fc5351d365,Power BI Premium Per User for Government Power BI Premium Per User Dept,PBI_PREMIUM_PER_USER_DEPT,f168a3fb-7bcf-4a27-98c3-c235ea4b78b4,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation @@ -5426,6 +5477,14 @@ Teams Premium (for Departments),Teams_Premium_(for_Departments),52ea0e27-ae73-49 Teams Premium (for Departments),Teams_Premium_(for_Departments),52ea0e27-ae73-4983-a08f-13561ebdb823,TEAMSPRO_VIRTUALAPPT,9104f592-f2a7-4f77-904c-ca5a5715883f,Microsoft Teams Premium Virtual Appointment Teams Premium (for Departments),Teams_Premium_(for_Departments),52ea0e27-ae73-4983-a08f-13561ebdb823,MCO_VIRTUAL_APPT,711413d0-b36e-4cd4-93db-0a50a4ab7ea3,Microsoft Teams Premium Virtual Appointments Teams Premium (for Departments),Teams_Premium_(for_Departments),52ea0e27-ae73-4983-a08f-13561ebdb823,TEAMSPRO_WEBINAR,78b58230-ec7e-4309-913c-93a45cc4735b,Microsoft Teams Premium Webinar +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,MICROSOFT_ECDN,85704d55-2e73-47ee-93b4-4b8ea14db92b,Microsoft eCDN +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_MGMT,0504111f-feb8-4a3c-992a-70280f9a2869,Microsoft Teams Premium Intelligent +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_CUST,cc8c0802-a325-43df-8cba-995d0c6cb373,Microsoft Teams Premium Personalized +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_PROTECTION,f8b44f54-18bb-46a3-9658-44ab58712968,Microsoft Teams Premium Secure +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_VIRTUALAPPT,9104f592-f2a7-4f77-904c-ca5a5715883f,Microsoft Teams Premium Virtual Appointment +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,MCO_VIRTUAL_APPT,711413d0-b36e-4cd4-93db-0a50a4ab7ea3,Microsoft Teams Premium Virtual Appointments +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_WEBINAR,78b58230-ec7e-4309-913c-93a45cc4735b,Microsoft Teams Premium Webinar +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,QUEUES_APP,ab2d4fb5-f80a-4bf1-a11d-7f1da254041b,Queues app for Microsoft Teams Teams Rooms Premium,MTR_PREM,4fb214cb-a430-4a91-9c91-4976763aa78f,MMR_P1,bdaa59a3-74fd-4137-981a-31d4f84eb8a0,Meeting Room Managed Services Teams Rooms Premium,MTR_PREM,4fb214cb-a430-4a91-9c91-4976763aa78f,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing Teams Rooms Premium,MTR_PREM,4fb214cb-a430-4a91-9c91-4976763aa78f,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System diff --git a/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 b/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 index 4a8548e0a741..ad3a24553976 100644 --- a/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 +++ b/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 @@ -24,106 +24,178 @@ function Add-CIPPScheduledTask { $Headers ) - $Table = Get-CIPPTable -TableName 'ScheduledTasks' - - 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" + try { + + $Table = Get-CIPPTable -TableName 'ScheduledTasks' + + 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 + + if ($null -eq $Param -or $Param -eq '' -or ($Param | Measure-Object).Count -eq 0) { + continue + } - $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 + # handle different object types in params + if ($Param -is [System.Collections.IDictionary] -or $Param[0].Key) { + Write-Information "Parameter $Key is a hashtable" + $ht = @{} + foreach ($p in $Param.GetEnumerator()) { + $ht[$p.Key] = $p.Value + } + $Parameters[$Key] = [PSCustomObject]$ht + Write-Information "Converted $Key to PSObject $($Parameters[$Key] | ConvertTo-Json -Compress)" + } elseif ($Param -is [System.Object[]] -and -not ($Param -is [string])) { + Write-Information "Parameter $Key is an enumerable object" + $Param = $Param | ForEach-Object { + if ($null -eq $_) { + # Skip null entries + return + } + if ($_ -is [System.Collections.IDictionary]) { + [PSCustomObject]$_ + } elseif ($_ -is [PSCustomObject]) { + $_ + } else { + $_ + } + } | Where-Object { $null -ne $_ } + $Parameters[$Key] = $Param + } else { + Write-Information "Parameter $Key is a simple value" + $Parameters[$Key] = $Param + } + } - if ($null -eq $Param -or $Param -eq '' -or ($Param | Measure-Object).Count -eq 0) { - continue + 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 ($Param -is [System.Collections.IDictionary] -or $Param.Key) { - $ht = @{} - foreach ($p in $Param.GetEnumerator()) { - $ht[$p.Key] = $p.Value + + $Parameters = ($Parameters | ConvertTo-Json -Depth 10 -Compress) + $AdditionalProperties = [System.Collections.Hashtable]@{} + foreach ($Prop in $task.AdditionalProperties) { + if ($null -eq $Prop.Value -or $Prop.Value -eq '' -or ($Prop.Value | Measure-Object).Count -eq 0) { + continue } - $Parameters[$Key] = [PSCustomObject]$ht + $AdditionalProperties[$Prop.Key] = $Prop.Value + } + $AdditionalProperties = ([PSCustomObject]$AdditionalProperties | ConvertTo-Json -Compress) + if ($Parameters -eq 'null') { $Parameters = '' } + if (!$Task.RowKey) { + $RowKey = (New-Guid).Guid } else { - $Parameters[$Key] = $Param + $RowKey = $Task.RowKey } - } - 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' - } + $Recurrence = if ([string]::IsNullOrEmpty($task.Recurrence.value)) { + $task.Recurrence + } else { + $task.Recurrence.value + } - $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 - } + 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 ',' + } - $Recurrence = if ([string]::IsNullOrEmpty($task.Recurrence.value)) { - $task.Recurrence - } else { - $task.Recurrence.value - } + # Handle tenant filter - support both single tenant and tenant groups + $tenantFilter = $task.TenantFilter.value ? $task.TenantFilter.value : $task.TenantFilter + $originalTenantFilter = $task.TenantFilter - 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 tenant filter is a complex object (from form), extract the value + if ($tenantFilter -is [PSCustomObject] -and $tenantFilter.value) { + $originalTenantFilter = $tenantFilter + $tenantFilter = $tenantFilter.value + } + + # If tenant filter is a string but still seems to be JSON, try to parse it + if ($tenantFilter -is [string] -and $tenantFilter.StartsWith('{')) { + try { + $parsedTenantFilter = $tenantFilter | ConvertFrom-Json + if ($parsedTenantFilter.value) { + $originalTenantFilter = $parsedTenantFilter + $tenantFilter = $parsedTenantFilter.value + } + } catch { + # If parsing fails, use the string as is + Write-Warning "Could not parse tenant filter JSON: $tenantFilter" + } + } + + $entity = @{ + PartitionKey = [string]'ScheduledTask' + TaskState = [string]'Planned' + RowKey = [string]$RowKey + Tenant = [string]$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' + } + + # Store the original tenant filter for group expansion during execution + if ($originalTenantFilter -is [PSCustomObject] -and $originalTenantFilter.type -eq 'Group') { + $entity['TenantGroup'] = [string]($originalTenantFilter | ConvertTo-Json -Compress) + } elseif ($originalTenantFilter -is [string] -and $originalTenantFilter.StartsWith('{')) { + # Check if it's a serialized group object + try { + $parsedOriginal = $originalTenantFilter | ConvertFrom-Json + if ($parsedOriginal.type -eq 'Group') { + $entity['TenantGroup'] = [string]$originalTenantFilter + } + } catch { + # Not a JSON object, ignore + } + } + 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)" + } catch { + Write-Warning "Failed to add scheduled task: $($_.Exception.Message)" + Write-Information $_.InvocationInfo.PositionMessage + $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message + throw "Could not add task: $ErrorMessage" } } diff --git a/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertLowTenantAlignment.ps1 b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertLowTenantAlignment.ps1 new file mode 100644 index 000000000000..bc8c5a04672d --- /dev/null +++ b/Modules/CIPPCore/Public/Alerts/Get-CIPPAlertLowTenantAlignment.ps1 @@ -0,0 +1,52 @@ +function Get-CIPPAlertLowTenantAlignment { + <# + .SYNOPSIS + Alert for low tenant alignment percentage + .DESCRIPTION + This alert checks tenant alignment scores against standards templates and alerts when the alignment percentage falls below the specified threshold. + .PARAMETER TenantFilter + The tenant to check alignment for + .PARAMETER InputValue + The minimum alignment percentage threshold (0-100). Default is 80. + .FUNCTIONALITY + Entrypoint + .EXAMPLE + Get-CIPPAlertLowTenantAlignment -TenantFilter "contoso.onmicrosoft.com" -InputValue 75 + #> + [CmdletBinding()] + param ( + [Parameter(Mandatory)] + $TenantFilter, + [Alias('input')] + [ValidateRange(0, 100)] + [int]$InputValue = 99 + ) + + try { + # Get tenant alignment data using the new function + $AlignmentData = Get-CIPPTenantAlignment -TenantFilter $TenantFilter + + if (-not $AlignmentData) { + Write-AlertMessage -tenant $TenantFilter -message "No alignment data found for tenant $TenantFilter. This may indicate no standards templates are configured or applied to this tenant." + return + } + + $LowAlignmentAlerts = $AlignmentData | Where-Object { $_.AlignmentScore -lt $InputValue } | ForEach-Object { + [PSCustomObject]@{ + TenantFilter = $_.TenantFilter + StandardName = $_.StandardName + StandardId = $_.StandardId + AlignmentScore = $_.AlignmentScore + LicenseMissingPercentage = $_.LicenseMissingPercentage + LatestDataCollection = $_.LatestDataCollection + } + } + + if ($LowAlignmentAlerts.Count -gt 0) { + Write-AlertTrace -cmdletName $MyInvocation.MyCommand -tenantFilter $TenantFilter -data $LowAlignmentAlerts + } + + } catch { + Write-AlertMessage -tenant $TenantFilter -message "Could not get tenant alignment data for $TenantFilter`: $(Get-NormalizedError -message $_.Exception.message)" + } +} diff --git a/Modules/CIPPCore/Public/Authentication/Get-CIPPHttpFunctions.ps1 b/Modules/CIPPCore/Public/Authentication/Get-CIPPHttpFunctions.ps1 index 6b2b0b626ba4..643130adb428 100644 --- a/Modules/CIPPCore/Public/Authentication/Get-CIPPHttpFunctions.ps1 +++ b/Modules/CIPPCore/Public/Authentication/Get-CIPPHttpFunctions.ps1 @@ -1,5 +1,5 @@ function Get-CIPPHttpFunctions { - Param( + param( [switch]$ByRole, [switch]$ByRoleGroup ) @@ -8,7 +8,7 @@ function Get-CIPPHttpFunctions { $Functions = Get-Command -Module CIPPCore | Where-Object { $_.Visibility -eq 'Public' -and $_.Name -match 'Invoke-*' } $Results = foreach ($Function in $Functions) { $Help = Get-Help $Function - if ($Help.Functionality -ne 'Entrypoint') { continue } + if ($Help.Functionality -notmatch 'Entrypoint') { continue } if ($Help.Role -eq 'Public') { continue } [PSCustomObject]@{ Function = $Function.Name diff --git a/Modules/CIPPCore/Public/Authentication/Get-CippAllowedPermissions.ps1 b/Modules/CIPPCore/Public/Authentication/Get-CippAllowedPermissions.ps1 new file mode 100644 index 000000000000..0f11f47d8684 --- /dev/null +++ b/Modules/CIPPCore/Public/Authentication/Get-CippAllowedPermissions.ps1 @@ -0,0 +1,182 @@ +function Get-CippAllowedPermissions { + <# + .SYNOPSIS + Retrieves the allowed permissions for the current user. + + .DESCRIPTION + This function retrieves the allowed permissions for the current user based on their role and the configured permissions in the CIPP system. + For admin/superadmin users, permissions are computed from base role include/exclude rules. + For editor/readonly users, permissions start from base role and are restricted by custom roles. + + .PARAMETER UserRoles + Array of user roles to compute permissions for. + + .OUTPUTS + Returns a list of allowed permissions for the current user. + #> + + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [string[]]$UserRoles + ) + + # Get all available permissions and base roles configuration + + $CIPPCoreModuleRoot = Get-Module -Name CIPPCore | Select-Object -ExpandProperty ModuleBase + $CIPPRoot = (Get-Item $CIPPCoreModuleRoot).Parent.Parent + $Version = (Get-Content -Path $CIPPRoot\version_latest.txt).trim() + $BaseRoles = Get-Content -Path $CIPPRoot\Config\cipp-roles.json | ConvertFrom-Json + $DefaultRoles = @('superadmin', 'admin', 'editor', 'readonly', 'anonymous', 'authenticated') + + $AllPermissionCacheTable = Get-CIPPTable -tablename 'cachehttppermissions' + $AllPermissionsRow = Get-CIPPAzDataTableEntity @AllPermissionCacheTable -Filter "PartitionKey eq 'HttpFunctions' and RowKey eq 'HttpFunctions' and Version eq '$($Version)'" + + if (-not $AllPermissionsRow) { + $AllPermissions = Get-CIPPHttpFunctions -ByRole | Select-Object -ExpandProperty Permission + $Entity = @{ + PartitionKey = 'HttpFunctions' + RowKey = 'HttpFunctions' + Version = [string]$Version + Permissions = [string]($AllPermissions | ConvertTo-Json -Compress) + } + Add-CIPPAzDataTableEntity @AllPermissionCacheTable -Entity $Entity -Force + } else { + $AllPermissions = $AllPermissionsRow.Permissions | ConvertFrom-Json + } + + $AllowedPermissions = [System.Collections.Generic.List[string]]::new() + + # Determine user's primary base role (highest priority first) + $BaseRole = $null + $PrimaryRole = $null + + if ($UserRoles -contains 'superadmin') { + $PrimaryRole = 'superadmin' + } elseif ($UserRoles -contains 'admin') { + $PrimaryRole = 'admin' + } elseif ($UserRoles -contains 'editor') { + $PrimaryRole = 'editor' + } elseif ($UserRoles -contains 'readonly') { + $PrimaryRole = 'readonly' + } + + if ($PrimaryRole) { + $BaseRole = $BaseRoles.PSObject.Properties | Where-Object { $_.Name -eq $PrimaryRole } | Select-Object -First 1 + } + + # Get custom roles (non-default roles) + $CustomRoles = $UserRoles | Where-Object { $DefaultRoles -notcontains $_ } + + # For admin and superadmin: Compute permissions from base role include/exclude rules + if ($PrimaryRole -in @('admin', 'superadmin')) { + Write-Information "Computing permissions for $PrimaryRole using base role rules" + + if ($BaseRole) { + # Start with all permissions and apply include/exclude rules + $BasePermissions = [System.Collections.Generic.List[string]]::new() + + # Apply include rules + foreach ($Include in $BaseRole.Value.include) { + $MatchingPermissions = $AllPermissions | Where-Object { $_ -like $Include } + foreach ($Permission in $MatchingPermissions) { + if ($BasePermissions -notcontains $Permission) { + $BasePermissions.Add($Permission) + } + } + } + + # Apply exclude rules + foreach ($Exclude in $BaseRole.Value.exclude) { + $ExcludedPermissions = $BasePermissions | Where-Object { $_ -like $Exclude } + foreach ($Permission in $ExcludedPermissions) { + $BasePermissions.Remove($Permission) | Out-Null + } + } + + foreach ($Permission in $BasePermissions) { + $AllowedPermissions.Add($Permission) + } + } + } + # For editor and readonly: Start with base role permissions and restrict with custom roles + elseif ($PrimaryRole -in @('editor', 'readonly')) { + Write-Information "Computing permissions for $PrimaryRole with custom role restrictions" + + if ($BaseRole) { + # Get base role permissions first + $BasePermissions = [System.Collections.Generic.List[string]]::new() + + # Apply include rules from base role + foreach ($Include in $BaseRole.Value.include) { + $MatchingPermissions = $AllPermissions | Where-Object { $_ -like $Include } + foreach ($Permission in $MatchingPermissions) { + if ($BasePermissions -notcontains $Permission) { + $BasePermissions.Add($Permission) + } + } + } + + # Apply exclude rules from base role + foreach ($Exclude in $BaseRole.Value.exclude) { + $ExcludedPermissions = $BasePermissions | Where-Object { $_ -like $Exclude } + foreach ($Permission in $ExcludedPermissions) { + $BasePermissions.Remove($Permission) | Out-Null + } + } + + # If custom roles exist, intersect with custom role permissions (restriction) + if ($CustomRoles.Count -gt 0) { + $CustomRolePermissions = [System.Collections.Generic.List[string]]::new() + + foreach ($CustomRole in $CustomRoles) { + try { + $RolePermissions = Get-CIPPRolePermissions -RoleName $CustomRole + foreach ($Permission in $RolePermissions.Permissions) { + if ($null -ne $Permission -and $Permission -is [string] -and $CustomRolePermissions -notcontains $Permission) { + $CustomRolePermissions.Add($Permission) + } + } + } catch { + Write-Warning "Failed to get permissions for custom role '$CustomRole': $($_.Exception.Message)" + } + } + + # Restrict base permissions to only those allowed by custom roles + $RestrictedPermissions = $BasePermissions | Where-Object { $CustomRolePermissions -contains $_ } + foreach ($Permission in $RestrictedPermissions) { + if ($null -ne $Permission -and $Permission -is [string]) { + $AllowedPermissions.Add($Permission) + } + } + } else { + # No custom roles, use base role permissions + foreach ($Permission in $BasePermissions) { + if ($null -ne $Permission -and $Permission -is [string]) { + $AllowedPermissions.Add($Permission) + } + } + } + } + } + # Handle users with only custom roles (no base role) + elseif ($CustomRoles.Count -gt 0) { + Write-Information 'Computing permissions for custom roles only' + + foreach ($CustomRole in $CustomRoles) { + try { + $RolePermissions = Get-CIPPRolePermissions -RoleName $CustomRole + foreach ($Permission in $RolePermissions.Permissions) { + if ($null -ne $Permission -and $Permission -is [string] -and $AllowedPermissions -notcontains $Permission) { + $AllowedPermissions.Add($Permission) + } + } + } catch { + Write-Warning "Failed to get permissions for custom role '$CustomRole': $($_.Exception.Message)" + } + } + } + + # Return sorted unique permissions + return ($AllowedPermissions | Sort-Object -Unique) +} diff --git a/Modules/CIPPCore/Public/Authentication/Test-CIPPAccess.ps1 b/Modules/CIPPCore/Public/Authentication/Test-CIPPAccess.ps1 index af8a7ff8dc2f..43b3de6e8141 100644 --- a/Modules/CIPPCore/Public/Authentication/Test-CIPPAccess.ps1 +++ b/Modules/CIPPCore/Public/Authentication/Test-CIPPAccess.ps1 @@ -8,26 +8,17 @@ function Test-CIPPAccess { # Get function help $FunctionName = 'Invoke-{0}' -f $Request.Params.CIPPEndpoint - try { - $Help = Get-Help $FunctionName -ErrorAction Stop - } catch {} + if ($FunctionName -ne 'Invoke-me') { + try { + $Help = Get-Help $FunctionName -ErrorAction Stop + } catch { + Write-Warning "Function '$FunctionName' not found" + } + } # Check help for role $APIRole = $Help.Role - if ($APIRole -eq 'Public') { - return $true - } - - # Get default roles from config - $CIPPCoreModuleRoot = Get-Module -Name CIPPCore | Select-Object -ExpandProperty ModuleBase - $CIPPRoot = (Get-Item $CIPPCoreModuleRoot).Parent.Parent - $BaseRoles = Get-Content -Path $CIPPRoot\Config\cipp-roles.json | ConvertFrom-Json - - if ($APIRole -eq 'Public') { - return $true - } - # Get default roles from config $CIPPCoreModuleRoot = Get-Module -Name CIPPCore | Select-Object -ExpandProperty ModuleBase $CIPPRoot = (Get-Item $CIPPCoreModuleRoot).Parent.Parent @@ -38,11 +29,6 @@ function Test-CIPPAccess { return $true } - # Get default roles from config - $CIPPCoreModuleRoot = Get-Module -Name CIPPCore | Select-Object -ExpandProperty ModuleBase - $CIPPRoot = (Get-Item $CIPPCoreModuleRoot).Parent.Parent - $BaseRoles = Get-Content -Path $CIPPRoot\Config\cipp-roles.json | ConvertFrom-Json - if ($Request.Headers.'x-ms-client-principal-idp' -eq 'aad' -and $Request.Headers.'x-ms-client-principal-name' -match '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$') { $Type = 'APIClient' # Direct API Access @@ -91,6 +77,22 @@ function Test-CIPPAccess { $CustomRoles = @('cipp-api') Write-Information "API Access: AppId=$($Request.Headers.'x-ms-client-principal-name'), IP=$IPAddress" } + if ($Request.Params.CIPPEndpoint -eq 'me') { + $Permissions = Get-CippAllowedPermissions -UserRoles $CustomRoles + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = ( + @{ + 'clientPrincipal' = @{ + appId = $Request.Headers.'x-ms-client-principal-name' + appRole = $CustomRoles + } + 'permissions' = $Permissions + } | ConvertTo-Json -Depth 5) + }) + return + } + } else { $Type = 'User' $User = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Request.Headers.'x-ms-client-principal')) | ConvertFrom-Json @@ -103,9 +105,26 @@ function Test-CIPPAccess { #Write-Information ($User | ConvertTo-Json -Depth 5) # Return user permissions if ($Request.Params.CIPPEndpoint -eq 'me') { + + if (!$User.userRoles) { + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = ( + @{ + 'clientPrincipal' = $null + 'permissions' = @() + } | ConvertTo-Json -Depth 5) + }) + } + + $Permissions = Get-CippAllowedPermissions -UserRoles $User.userRoles Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK - Body = (@{ 'clientPrincipal' = $User } | ConvertTo-Json -Depth 5) + Body = ( + @{ + 'clientPrincipal' = $User + 'permissions' = $Permissions + } | ConvertTo-Json -Depth 5) }) return } @@ -186,10 +205,39 @@ function Test-CIPPAccess { if ((($Permission.AllowedTenants | Measure-Object).Count -eq 0 -or $Permission.AllowedTenants -contains 'AllTenants') -and (($Permission.BlockedTenants | Measure-Object).Count -eq 0)) { @('AllTenants') } else { - if ($Permission.AllowedTenants -contains 'AllTenants') { - $Permission.AllowedTenants = $Tenants.customerId + # Expand tenant groups to individual tenant IDs + $ExpandedAllowedTenants = foreach ($AllowedItem in $Permission.AllowedTenants) { + if ($AllowedItem -is [PSCustomObject] -and $AllowedItem.type -eq 'Group') { + try { + $GroupMembers = Expand-CIPPTenantGroups -TenantFilter @($AllowedItem) + $GroupMembers | ForEach-Object { $_.addedFields.customerId } + } catch { + Write-Warning "Failed to expand tenant group '$($AllowedItem.label)': $($_.Exception.Message)" + @() + } + } else { + $AllowedItem + } } - $Permission.AllowedTenants | Where-Object { $Permission.BlockedTenants -notcontains $_ } + + $ExpandedBlockedTenants = foreach ($BlockedItem in $Permission.BlockedTenants) { + if ($BlockedItem -is [PSCustomObject] -and $BlockedItem.type -eq 'Group') { + try { + $GroupMembers = Expand-CIPPTenantGroups -TenantFilter @($BlockedItem) + $GroupMembers | ForEach-Object { $_.addedFields.customerId } + } catch { + Write-Warning "Failed to expand blocked tenant group '$($BlockedItem.label)': $($_.Exception.Message)" + @() + } + } else { + $BlockedItem + } + } + + if ($ExpandedAllowedTenants -contains 'AllTenants') { + $ExpandedAllowedTenants = $Tenants.customerId + } + $ExpandedAllowedTenants | Where-Object { $ExpandedBlockedTenants -notcontains $_ } } } return $LimitedTenantList @@ -214,13 +262,45 @@ function Test-CIPPAccess { $TenantAllowed = $false } else { $Tenant = ($Tenants | Where-Object { $TenantFilter -eq $_.customerId -or $TenantFilter -eq $_.defaultDomainName }).customerId - if ($Role.AllowedTenants -contains 'AllTenants') { + + # Expand allowed tenant groups to individual tenant IDs + $ExpandedAllowedTenants = foreach ($AllowedItem in $Role.AllowedTenants) { + if ($AllowedItem -is [PSCustomObject] -and $AllowedItem.type -eq 'Group') { + try { + $GroupMembers = Expand-CIPPTenantGroups -TenantFilter @($AllowedItem) + $GroupMembers | ForEach-Object { $_.addedFields.customerId } + } catch { + Write-Warning "Failed to expand allowed tenant group '$($AllowedItem.label)': $($_.Exception.Message)" + @() + } + } else { + $AllowedItem + } + } + + # Expand blocked tenant groups to individual tenant IDs + $ExpandedBlockedTenants = foreach ($BlockedItem in $Role.BlockedTenants) { + if ($BlockedItem -is [PSCustomObject] -and $BlockedItem.type -eq 'Group') { + try { + $GroupMembers = Expand-CIPPTenantGroups -TenantFilter @($BlockedItem) + $GroupMembers | ForEach-Object { $_.addedFields.customerId } + } catch { + Write-Warning "Failed to expand blocked tenant group '$($BlockedItem.label)': $($_.Exception.Message)" + @() + } + } else { + $BlockedItem + } + } + + if ($ExpandedAllowedTenants -contains 'AllTenants') { $AllowedTenants = $Tenants.customerId } else { - $AllowedTenants = $Role.AllowedTenants + $AllowedTenants = $ExpandedAllowedTenants } + if ($Tenant) { - $TenantAllowed = $AllowedTenants -contains $Tenant -and $Role.BlockedTenants -notcontains $Tenant + $TenantAllowed = $AllowedTenants -contains $Tenant -and $ExpandedBlockedTenants -notcontains $Tenant if (!$TenantAllowed) { continue } break } else { diff --git a/Modules/CIPPCore/Public/Clear-CIPPImmutableId.ps1 b/Modules/CIPPCore/Public/Clear-CIPPImmutableId.ps1 index ca9d60c172de..eaba79df769d 100644 --- a/Modules/CIPPCore/Public/Clear-CIPPImmutableId.ps1 +++ b/Modules/CIPPCore/Public/Clear-CIPPImmutableId.ps1 @@ -2,21 +2,22 @@ function Clear-CIPPImmutableId { [CmdletBinding()] param ( $TenantFilter, - $userid, + $UserID, $Headers, - $APIName + $APIName = 'Clear Immutable ID' ) try { $Body = [pscustomobject]@{ onPremisesImmutableId = $null } $Body = ConvertTo-Json -InputObject $Body -Depth 5 -Compress - $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$userid" -tenantid $TenantFilter -type PATCH -body $Body - Write-LogMessage -headers $Headers -API $APIName -message "Successfully cleared immutable ID for $userid" -sev Info - return 'Successfully cleared immutable ID for user.' + $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$UserID" -tenantid $TenantFilter -type PATCH -body $Body + $Result = "Successfully cleared immutable ID for user $UserID" + Write-LogMessage -headers $Headers -API $APIName -message $Result -sev Info -tenant $TenantFilter + return $Result } catch { $ErrorMessage = Get-CippException -Exception $_ - $Message = "Could not clear immutable ID for $($userid): $($ErrorMessage.NormalizedError)" - Write-LogMessage -headers $Headers -API $APIName -message $Message -sev Error -LogData $ErrorMessage - return $Message + $Result = "Failed to clear immutable ID for $($UserID). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Result -sev Error -tenant $TenantFilter -LogData $ErrorMessage + throw $Result } } diff --git a/Modules/CIPPCore/Public/Compare-CIPPIntuneObject.ps1 b/Modules/CIPPCore/Public/Compare-CIPPIntuneObject.ps1 index 579fdcd913f6..2de562a1fdf8 100644 --- a/Modules/CIPPCore/Public/Compare-CIPPIntuneObject.ps1 +++ b/Modules/CIPPCore/Public/Compare-CIPPIntuneObject.ps1 @@ -257,7 +257,7 @@ function Compare-CIPPIntuneObject { } } } - Default { + default { if ($settingInstance.simpleSettingValue?.value) { $label = if ($intuneObj?.displayName) { $intuneObj.displayName @@ -337,6 +337,9 @@ function Compare-CIPPIntuneObject { } else { $child.choiceSettingValue.value } + if (!$childValue -and $child.simpleSettingValue.value) { + $childValue = $child.simpleSettingValue.value + } } # Add object to our temporary list @@ -351,7 +354,7 @@ function Compare-CIPPIntuneObject { } } } - Default { + default { if ($settingInstance.simpleSettingValue?.value) { $label = if ($intuneObj?.displayName) { $intuneObj.displayName diff --git a/Modules/CIPPCore/Public/ConversionTable.csv b/Modules/CIPPCore/Public/ConversionTable.csv index 704f7c507d5f..5b7cea1f09ea 100644 --- a/Modules/CIPPCore/Public/ConversionTable.csv +++ b/Modules/CIPPCore/Public/ConversionTable.csv @@ -20,6 +20,7 @@ Clipchamp Premium,Clipchamp_Premium,0fe440c5-f2bf-442b-a4f4-9a7af77a200b,ONEDRIV Clipchamp Standard,Clipchamp_Standard,481f3bc2-5756-4b28-9375-5c8c86b99e6b,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Clipchamp Standard,Clipchamp_Standard,481f3bc2-5756-4b28-9375-5c8c86b99e6b,CLIPCHAMP,a1ace008-72f3-4ea0-8dac-33b3a23a2472,Microsoft Clipchamp Clipchamp Standard,Clipchamp_Standard,481f3bc2-5756-4b28-9375-5c8c86b99e6b,ONEDRIVECLIPCHAMP,f7e5b77d-f293-410a-bae8-f941f19fe680,OneDrive for Business (Clipchamp) +Clipchamp Premium Add-on,Clipchamp_Premium_Add_on,4b2c20e4-939d-4bf4-9dd8-6870240cfe19,CLIPCHAMP_PREMIUM,430b908f-78e1-4812-b045-cf83320e7d5d,Microsoft Clipchamp Premium Microsoft 365 Audio Conferencing,MCOMEETADV,0c266dff-15dd-4b49-8397-2bb16070ed52,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing Microsoft Entra ID Basic,AAD_BASIC,2b9c8e7c-319c-43a2-a2a0-48c5c6161de7,AAD_BASIC,c4da7f8a-5ee2-4c99-a7e1-87d2df57f6fe,Microsoft Entra BASIC Microsoft Entra ID P1,AAD_PREMIUM,078d2b04-f1bd-4111-bbd4-b4b1b354cef4,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 @@ -418,6 +419,13 @@ Dynamics 365 Guides vTrial,Dynamics_365_Guides_vTrial,99cb3f83-fbec-4aa1-8262-96 Dynamics 365 Guides vTrial,Dynamics_365_Guides_vTrial,99cb3f83-fbec-4aa1-8262-9679e6df7c53,DYN365_CDS_VIRAL,17ab22cd-a0b3-4536-910a-cb6eb12696c0,Common Data Service Dynamics 365 Guides vTrial,Dynamics_365_Guides_vTrial,99cb3f83-fbec-4aa1-8262-9679e6df7c53,POWER_APPS_DYN365_VIRAL_TRIAL_MIXED_REALITY,066e2fd1-ba15-40e7-aa96-d6636b1cdf71,Power Apps for Dynamics 365 Mixed Reality Dynamics 365 Guides vTrial,Dynamics_365_Guides_vTrial,99cb3f83-fbec-4aa1-8262-9679e6df7c53,POWER_AUTOMATE_DYN365_VIRAL_TRIAL_MIXED_REALITY,26fa8a18-2812-4b3d-96b4-864818ce26be,Power Automate for Dynamics 365 Mixed Reality +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,Forms_Pro_Talent,1c4ae475-5608-43fa-b3f7-d20e07cf24b4,Microsoft Dynamics 365 Customer Voice for Talent +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,D365_HR_SELF_SERVICE_OPS,835b837b-63c1-410e-bf6b-bdef201ad129,Dynamics 365 Human Resource Self Service +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,D365_HR_OPS,8b21a5dc-5485-49ed-a2d4-0e772c830f6d,Dynamics 365 Human Resources +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,D365_HR_Attach,3219525a-4064-45ec-9c35-a33ea6b39a49,Dynamics 365 Human Resources Attach +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,D365_HR_ATTACH_OPS,90d8cb62-e98a-4639-8342-8c7d2c8215ba,Dynamics 365 Human Resources Attach License +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 Hybrid Connector,CRM_HYBRIDCONNECTOR,de176c31-616d-4eae-829a-718918d7ec23,CRM_HYBRIDCONNECTOR,0210d5c8-49d2-4dd1-a01b-a91c7c14e0bf,CRM Hybrid Connector Dynamics 365 Hybrid Connector,CRM_HYBRIDCONNECTOR,de176c31-616d-4eae-829a-718918d7ec23,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 for Marketing Additional Application,DYN365_MARKETING_APPLICATION_ADDON,99c5688b-6c75-4496-876f-07f0fbd69add,DYN365_MARKETING_APPLICATION_ADDON,51cf0638-4861-40c0-8b20-1161ab2f80be,Dynamics 365 for Marketing Additional Application @@ -967,111 +975,129 @@ Microsoft 365 A3 - Unattended License for students use benefit,M365EDU_A3_STUUSE Microsoft 365 A3 - Unattended License for students use benefit,M365EDU_A3_STUUSEBNFT_RPA1,1aa94593-ca12-4254-a738-81a5972958e8,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune for Education Microsoft 365 A3 - Unattended License for students use benefit,M365EDU_A3_STUUSEBNFT_RPA1,1aa94593-ca12-4254-a738-81a5972958e8,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 Microsoft 365 A3 - Unattended License for students use benefit,M365EDU_A3_STUUSEBNFT_RPA1,1aa94593-ca12-4254-a738-81a5972958e8,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CDS_O365_P3,afa73018-811e-46e9-988f-f75d2b1b8430,Common Data Service for Teams -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,LOCKBOX_ENTERPRISE,9f431833-0334-42de-a7dc-70aa40db46db,Customer Lockbox -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_Exchange,cd31b152-6326-4d1b-ae1b-997b625182e6,Data Classification in Microsoft 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCHANGE_S_ENTERPRISE,efb87545-963c-4e0d-99df-69c6916d9eb0,Exchange Online (Plan 2) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Content_Explorer,d9fa6af4-e046-4c89-9226-729a0786685d,Information Protection and Governance Analytics - Premium -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ContentExplorer_Standard,2b815d45-56e4-4e3a-b65c-66cb9175b560,Information Protection and Governance Analytics – Standard -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_CLP2,efb0351d-3b08-4503-993d-383af8de41e3,Information Protection for Office 365 - Premium -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_CLP1,5136a095-5cf0-4aff-bec3-e84448b38ea5,Information Protection for Office 365 - Standard -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,M365_ADVANCED_AUDITING,2f442157-a11c-46b9-ae5b-6e39ff4e5849,Microsoft 365 Advanced Auditing -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,OFFICESUBSCRIPTION,43de0ff5-c92c-492b-9116-175376d08c38,Microsoft 365 Apps for Enterprise -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_COMMUNICATION_COMPLIANCE,a413a9ff-720c-4822-98ef-2f37c2a21f4c,Microsoft 365 Communication Compliance -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MTP,bf28f719-7844-4079-9c78-c1307898e192,Microsoft 365 Defender -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFTBOOKINGS,199a5c09-e0ca-4e37-8f7c-b05d533e1ea2,Microsoft Bookings -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMUNICATIONS_DLP,6dc145d6-95dd-4191-b9c3-185575ee6f6b,Microsoft Communications DLP -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CUSTOMER_KEY,6db1f1db-2b46-403f-be40-e39395f08dbb,Microsoft Customer Key -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,DATA_INVESTIGATIONS,46129a58-a698-46f0-aa5b-17f6586297d9,Microsoft Data Investigations -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ATP_ENTERPRISE,f20fedf3-f3c3-43c3-8267-2bfdd51c0939,Microsoft Defender for Office 365 (Plan 1) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,THREAT_INTELLIGENCE,8e0c0a52-6a6c-4d40-8370-dd62790dcd70,Microsoft Defender for Office 365 (Plan 2) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCEL_PREMIUM,531ee2f8-b1cb-453b-9c21-d2180d014ca5,Microsoft Excel Advanced Analytics -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,OFFICE_FORMS_PLAN_3,96c1e14a-ef43-418d-b115-9636cdaa8eed,Microsoft Forms (Plan 3) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INFO_GOVERNANCE,e26c2fcc-ab91-4a61-b35c-03cdc8dddf66,Microsoft Information Governance -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INSIDER_RISK,d587c7a3-bda9-4f99-8776-9bcf59c84f75,Microsoft Insider Risk Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,KAIZALA_STANDALONE,0898bdbb-73b0-471a-81e5-20f1fe4dd66e,Microsoft Kaizala Pro -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ML_CLASSIFICATION,d2d51368-76c9-4317-ada2-a12c004c432f,Microsoft ML-Based Classification -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCHANGE_ANALYTICS,34c0d7a0-a70f-4668-9238-47f9fc208882,Microsoft MyAnalytics (Full) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RECORDS_MANAGEMENT,65cc641f-cccd-4643-97e0-a17e3045e541,Microsoft Records Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_SEARCH,94065c59-bc8e-4e8b-89e5-5138d471eaff,Microsoft Search -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Deskless,8c7d2df8-86f0-4902-b2ed-a0458298f3b3,Microsoft StaffHub -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,STREAM_O365_E5,6c6042f5-6f01-4d67-b8c1-eb99d36eed3e,Microsoft Stream for Office 365 E5 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,TEAMS1,57ff2da0-773e-42df-b2af-ffb7a2317929,Microsoft Teams -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MINECRAFT_EDUCATION_EDITION,4c246bbc-f513-4311-beff-eba54c353256,Minecraft Education Edition -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_O365,882e1d05-acd1-4ccb-8708-6ee03664b117,Mobile Device Management for Office 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Nucleus,db4d623d-b514-490b-b7ef-8885eee514de,Nucleus -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EQUIVIO_ANALYTICS,4de31727-a228-4ec3-a5bf-8e45b5ca48cc,Office 365 Advanced eDiscovery -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ADALLOM_S_O365,8c098270-9dd4-4350-9b30-ba4703f3b36b,Office 365 Cloud App Security -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PAM_ENTERPRISE,b1188c4c-1b36-4018-b48b-ee07604f6feb,Office 365 Privileged Access Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SAFEDOCS,bf6f5520-59e3-4f82-974b-7dbbc4fd27c7,Office 365 SafeDocs -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SHAREPOINTWAC_EDU,e03c7e47-402c-463c-ab25-949079bedb21,Office for the Web for Education -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,POWERAPPS_O365_P3,9c0dab89-a30c-4117-86e7-97bda240acd2,Power Apps for Office 365 (Plan 3) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,BI_AZURE_P2,70d33638-9c74-4d01-bfd3-562de28bd4ba,Power BI Pro -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PREMIUM_ENCRYPTION,617b097b-4b93-4ede-83de-5f075bb5fb2f,Premium Encryption in Office 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PROJECT_O365_P3,b21a6b06-1988-436e-a07b-51ec6d9f52ad,Project for Office (Plan E5) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMUNICATIONS_COMPLIANCE,41fcdd7d-4733-4863-9cf4-c65b83ce2df4,Microsoft Communications Compliance -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INSIDER_RISK_MANAGEMENT,9d0c4ee5-e4a1-4625-ab39-d82b619b1a34,Microsoft Insider Risk Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SCHOOL_DATA_SYNC_P2,500b6a2a-7a50-4f40-b5f9-160e5b8c2f48,School Data Sync (Plan 2) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SHAREPOINTENTERPRISE_EDU,63038b2c-28d0-45f6-bc36-33062963b498,SharePoint (Plan 2) for Education -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SWAY,a23b959c-7ce8-4e57-9140-b90eb88a9e97,Sway -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,BPOS_S_TODO_3,3fb82609-8c27-4f7b-bd51-30634711ee67,To-Do (Plan 3) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,VIVA_LEARNING_SEEDED,b76fb638-6ba6-402a-b9f9-83d28acb3d86,Viva Learning Seeded -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WHITEBOARD_PLAN3,4a51bca5-1eff-43f5-878c-177680f191af,Whiteboard (Plan 3) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WINDEFATP,871d91ec-ec1a-452b-a83f-bd76c7d770ef,Microsoft Defender for Endpoint -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFTENDPOINTDLP,64bfac92-2b17-4482-b5e5-a0304429de3e,Microsoft Endpoint DLP -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,UNIVERSAL_PRINT_01,795f6fe0-cc4d-4773-b050-5dde4dc704c9,Universal Print -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Virtualization Rights for Windows 10 (E3/E5+VDA),e7c91390-7625-45be-94e0-e16907e03118,Windows 10/11 Enterprise -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WINDOWSUPDATEFORBUSINESS_DEPLOYMENTSERVICE,7bf960f6-2cd9-443a-8046-5dbff9558365,Windows Update for Business Deployment Service -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_PREMIUM_P2,eec0eb4f-6444-4f95-aba0-50c24d67f998,Microsoft Entra ID P2 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_PREMIUM,6c57d4b6-3b23-47a5-9bc9-69f17b4947b3,Azure Information Protection Premium P1 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_PREMIUM2,5689bec4-755d-4753-8b61-40975025187c,Azure Information Protection Premium P2 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,DYN365_CDS_O365_P3,28b0fa46-c39a-4188-89e2-58e979a6b014,Common Data Service -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MFA_PREMIUM,8a256a2b-b617-496d-b51b-e76466e88db0,Microsoft Azure Multi-Factor Authentication -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ADALLOM_S_STANDALONE,2e2ddb96-6af9-4b1d-a3f0-d6ecfd22edb2,Microsoft Defender for Cloud Apps -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ATA,14ab5db5-e6c4-4b20-b4bc-13e36fd2227f,Microsoft Defender for Identity -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune for Education -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,FLOW_O365_P3,07699545-9485-468e-95b6-2fca3738be01,Power Automate for Office 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,POWER_VIRTUAL_AGENTS_O365_P3,ded3d325-1bdc-453e-8432-5bac26d7a014,Power Virtual Agents for Office 365 -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CDS_O365_P3,afa73018-811e-46e9-988f-f75d2b1b8430,Common Data Service for Teams +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,LOCKBOX_ENTERPRISE,9f431833-0334-42de-a7dc-70aa40db46db,Customer Lockbox +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CustomerLockboxA_Enterprise,3ec18638-bd4c-4d3b-8905-479ed636b83e,Customer Lockbox (A) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_Exchange,cd31b152-6326-4d1b-ae1b-997b625182e6,Data Classification in Microsoft 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMON_DEFENDER_PLATFORM_FOR_OFFICE,a312bdeb-1e21-40d0-84b1-0e73f128144f,Defender Platform for Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCHANGE_S_ENTERPRISE,efb87545-963c-4e0d-99df-69c6916d9eb0,Exchange Online (Plan 2) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,GRAPH_CONNECTORS_SEARCH_INDEX,a6520331-d7d4-4276-95f5-15c0933bc757,Graph Connectors Search with Index +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Content_Explorer,d9fa6af4-e046-4c89-9226-729a0786685d,Information Protection and Governance Analytics - Premium +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ContentExplorer_Standard,2b815d45-56e4-4e3a-b65c-66cb9175b560,Information Protection and Governance Analytics – Standard +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_CLP2,efb0351d-3b08-4503-993d-383af8de41e3,Information Protection for Office 365 - Premium +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_CLP1,5136a095-5cf0-4aff-bec3-e84448b38ea5,Information Protection for Office 365 - Standard +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,M365_ADVANCED_AUDITING,2f442157-a11c-46b9-ae5b-6e39ff4e5849,Microsoft 365 Advanced Auditing +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,OFFICESUBSCRIPTION,43de0ff5-c92c-492b-9116-175376d08c38,Microsoft 365 Apps for enterprise +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,M365_AUDIT_PLATFORM,f6de4823-28fa-440b-b886-4783fa86ddba,Microsoft 365 Audit Platform +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_COMMUNICATION_COMPLIANCE,a413a9ff-720c-4822-98ef-2f37c2a21f4c,Microsoft 365 Communication Compliance +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MTP,bf28f719-7844-4079-9c78-c1307898e192,Microsoft 365 Defender +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFTBOOKINGS,199a5c09-e0ca-4e37-8f7c-b05d533e1ea2,Microsoft Bookings +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CLIPCHAMP,a1ace008-72f3-4ea0-8dac-33b3a23a2472,Microsoft Clipchamp +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMUNICATIONS_DLP,6dc145d6-95dd-4191-b9c3-185575ee6f6b,Microsoft Communications DLP +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CUSTOMER_KEY,6db1f1db-2b46-403f-be40-e39395f08dbb,Microsoft Customer Key +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ATP_ENTERPRISE,f20fedf3-f3c3-43c3-8267-2bfdd51c0939,Microsoft Defender for Office 365 (Plan 1) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,THREAT_INTELLIGENCE,8e0c0a52-6a6c-4d40-8370-dd62790dcd70,Microsoft Defender for Office 365 (Plan 2) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCEL_PREMIUM,531ee2f8-b1cb-453b-9c21-d2180d014ca5,Microsoft Excel Advanced Analytics +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,OFFICE_FORMS_PLAN_3,96c1e14a-ef43-418d-b115-9636cdaa8eed,Microsoft Forms (Plan 3) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INFO_GOVERNANCE,e26c2fcc-ab91-4a61-b35c-03cdc8dddf66,Microsoft Information Governance +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INSIDER_RISK,d587c7a3-bda9-4f99-8776-9bcf59c84f75,Microsoft Insider Risk Management +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INSIDER_RISK_MANAGEMENT,9d0c4ee5-e4a1-4625-ab39-d82b619b1a34,Microsoft Insider Risk Management - Exchange +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,KAIZALA_STANDALONE,0898bdbb-73b0-471a-81e5-20f1fe4dd66e,Microsoft Kaizala Pro +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_LOOP,c4b8c31a-fb44-4c65-9837-a21f55fcabda,Microsoft Loop +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ML_CLASSIFICATION,d2d51368-76c9-4317-ada2-a12c004c432f,Microsoft ML-Based Classification +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCHANGE_ANALYTICS,34c0d7a0-a70f-4668-9238-47f9fc208882,Microsoft MyAnalytics (Full) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RECORDS_MANAGEMENT,65cc641f-cccd-4643-97e0-a17e3045e541,Microsoft Records Management +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_SEARCH,94065c59-bc8e-4e8b-89e5-5138d471eaff,Microsoft Search +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Deskless,8c7d2df8-86f0-4902-b2ed-a0458298f3b3,Microsoft StaffHub +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,STREAM_O365_E5,6c6042f5-6f01-4d67-b8c1-eb99d36eed3e,Microsoft Stream for Office 365 E5 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,TEAMS1,57ff2da0-773e-42df-b2af-ffb7a2317929,Microsoft Teams +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MINECRAFT_EDUCATION_EDITION,4c246bbc-f513-4311-beff-eba54c353256,Minecraft Education Edition +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_O365,882e1d05-acd1-4ccb-8708-6ee03664b117,Mobile Device Management for Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Nucleus,db4d623d-b514-490b-b7ef-8885eee514de,Nucleus +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EQUIVIO_ANALYTICS,4de31727-a228-4ec3-a5bf-8e45b5ca48cc,Office 365 Advanced eDiscovery +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ADALLOM_S_O365,8c098270-9dd4-4350-9b30-ba4703f3b36b,Office 365 Cloud App Security +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PAM_ENTERPRISE,b1188c4c-1b36-4018-b48b-ee07604f6feb,Office 365 Privileged Access Management +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SAFEDOCS,bf6f5520-59e3-4f82-974b-7dbbc4fd27c7,Office 365 SafeDocs +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SHAREPOINTWAC_EDU,e03c7e47-402c-463c-ab25-949079bedb21,Office for the Web for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,POWERAPPS_O365_P3,9c0dab89-a30c-4117-86e7-97bda240acd2,Power Apps for Office 365 (Plan 3) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,BI_AZURE_P2,70d33638-9c74-4d01-bfd3-562de28bd4ba,Power BI Pro +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PREMIUM_ENCRYPTION,617b097b-4b93-4ede-83de-5f075bb5fb2f,Premium Encryption in Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PROJECT_O365_P3,b21a6b06-1988-436e-a07b-51ec6d9f52ad,Project for Office (Plan E5) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PURVIEW_DISCOVERY,c948ea65-2053-4a5a-8a62-9eaaaf11b522,Purview Discovery +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Bing_Chat_Enterprise,0d0c0d31-fae7-41f2-b909-eaf4d7f26dba,RETIRED - Commercial data protection for Microsoft Copilot +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMUNICATIONS_COMPLIANCE,41fcdd7d-4733-4863-9cf4-c65b83ce2df4,RETIRED - Microsoft Communications Compliance +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,DATA_INVESTIGATIONS,46129a58-a698-46f0-aa5b-17f6586297d9,Retired - Microsoft Data Investigations +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SCHOOL_DATA_SYNC_P2,500b6a2a-7a50-4f40-b5f9-160e5b8c2f48,School Data Sync (Plan 2) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SHAREPOINTENTERPRISE_EDU,63038b2c-28d0-45f6-bc36-33062963b498,SharePoint (Plan 2) for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SWAY,a23b959c-7ce8-4e57-9140-b90eb88a9e97,Sway +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,BPOS_S_TODO_3,3fb82609-8c27-4f7b-bd51-30634711ee67,To-Do (Plan 3) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,VIVA_LEARNING_SEEDED,b76fb638-6ba6-402a-b9f9-83d28acb3d86,Viva Learning Seeded +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WHITEBOARD_PLAN3,4a51bca5-1eff-43f5-878c-177680f191af,Whiteboard (Plan 3) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WINDEFATP,871d91ec-ec1a-452b-a83f-bd76c7d770ef,Microsoft Defender for Endpoint +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFTENDPOINTDLP,64bfac92-2b17-4482-b5e5-a0304429de3e,Microsoft Endpoint DLP +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,UNIVERSAL_PRINT_01,795f6fe0-cc4d-4773-b050-5dde4dc704c9,Universal Print +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Virtualization Rights for Windows 10 (E3/E5+VDA),e7c91390-7625-45be-94e0-e16907e03118,Windows 10/11 Enterprise +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WINDOWSUPDATEFORBUSINESS_DEPLOYMENTSERVICE,7bf960f6-2cd9-443a-8046-5dbff9558365,Windows Update for Business Deployment Service +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_PREMIUM,6c57d4b6-3b23-47a5-9bc9-69f17b4947b3,Azure Information Protection Premium P1 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_PREMIUM2,5689bec4-755d-4753-8b61-40975025187c,Azure Information Protection Premium P2 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,DYN365_CDS_O365_P3,28b0fa46-c39a-4188-89e2-58e979a6b014,Common Data Service +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Intune_ServiceNow,3eeb8536-fecf-41bf-a3f8-d6f17a9f3efc,Intune ServiceNow Integration +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MFA_PREMIUM,8a256a2b-b617-496d-b51b-e76466e88db0,Microsoft Azure Multi-Factor Authentication +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ADALLOM_S_STANDALONE,2e2ddb96-6af9-4b1d-a3f0-d6ecfd22edb2,Microsoft Defender for Cloud Apps +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ATA,14ab5db5-e6c4-4b20-b4bc-13e36fd2227f,Microsoft Defender for Identity +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_PREMIUM_P2,eec0eb4f-6444-4f95-aba0-50c24d67f998,Microsoft Entra ID P2 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune Plan 1 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune Plan 1 for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,FLOW_O365_P3,07699545-9485-468e-95b6-2fca3738be01,Power Automate for Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,POWER_VIRTUAL_AGENTS_O365_P3,ded3d325-1bdc-453e-8432-5bac26d7a014,Power Virtual Agents for Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,REMOTE_HELP,a4c6cf29-1168-4076-ba5c-e8fe0e62b17e,Remote help +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,CDS_O365_P3,afa73018-811e-46e9-988f-f75d2b1b8430,Common Data Service for Teams Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,LOCKBOX_ENTERPRISE,9f431833-0334-42de-a7dc-70aa40db46db,Customer Lockbox +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,CustomerLockboxA_Enterprise,3ec18638-bd4c-4d3b-8905-479ed636b83e,Customer Lockbox (A) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MIP_S_Exchange,cd31b152-6326-4d1b-ae1b-997b625182e6,Data Classification in Microsoft 365 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,COMMON_DEFENDER_PLATFORM_FOR_OFFICE,a312bdeb-1e21-40d0-84b1-0e73f128144f,Defender Platform for Office 365 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,EXCHANGE_S_ENTERPRISE,efb87545-963c-4e0d-99df-69c6916d9eb0,Exchange Online (Plan 2) +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,GRAPH_CONNECTORS_SEARCH_INDEX,a6520331-d7d4-4276-95f5-15c0933bc757,Graph Connectors Search with Index Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,Content_Explorer,d9fa6af4-e046-4c89-9226-729a0786685d,Information Protection and Governance Analytics - Premium Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ContentExplorer_Standard,2b815d45-56e4-4e3a-b65c-66cb9175b560,Information Protection and Governance Analytics – Standard Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MIP_S_CLP2,efb0351d-3b08-4503-993d-383af8de41e3,Information Protection for Office 365 - Premium Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MIP_S_CLP1,5136a095-5cf0-4aff-bec3-e84448b38ea5,Information Protection for Office 365 - Standard Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,M365_ADVANCED_AUDITING,2f442157-a11c-46b9-ae5b-6e39ff4e5849,Microsoft 365 Advanced Auditing -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,OFFICESUBSCRIPTION,43de0ff5-c92c-492b-9116-175376d08c38,Microsoft 365 Apps for Enterprise +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,OFFICESUBSCRIPTION,43de0ff5-c92c-492b-9116-175376d08c38,Microsoft 365 Apps for enterprise Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,M365_AUDIT_PLATFORM,f6de4823-28fa-440b-b886-4783fa86ddba,Microsoft 365 Audit Platform Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MICROSOFT_COMMUNICATION_COMPLIANCE,a413a9ff-720c-4822-98ef-2f37c2a21f4c,Microsoft 365 Communication Compliance Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MTP,bf28f719-7844-4079-9c78-c1307898e192,Microsoft 365 Defender +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MICROSOFTBOOKINGS,199a5c09-e0ca-4e37-8f7c-b05d533e1ea2,Microsoft Bookings +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,CLIPCHAMP,a1ace008-72f3-4ea0-8dac-33b3a23a2472,Microsoft Clipchamp Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,COMMUNICATIONS_DLP,6dc145d6-95dd-4191-b9c3-185575ee6f6b,Microsoft Communications DLP Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,CUSTOMER_KEY,6db1f1db-2b46-403f-be40-e39395f08dbb,Microsoft Customer Key -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,DATA_INVESTIGATIONS,46129a58-a698-46f0-aa5b-17f6586297d9,Microsoft Data Investigations Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ATP_ENTERPRISE,f20fedf3-f3c3-43c3-8267-2bfdd51c0939,Microsoft Defender for Office 365 (Plan 1) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,THREAT_INTELLIGENCE,8e0c0a52-6a6c-4d40-8370-dd62790dcd70,Microsoft Defender for Office 365 (Plan 2) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,EXCEL_PREMIUM,531ee2f8-b1cb-453b-9c21-d2180d014ca5,Microsoft Excel Advanced Analytics Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,OFFICE_FORMS_PLAN_3,96c1e14a-ef43-418d-b115-9636cdaa8eed,Microsoft Forms (Plan 3) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INFO_GOVERNANCE,e26c2fcc-ab91-4a61-b35c-03cdc8dddf66,Microsoft Information Governance Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INSIDER_RISK,d587c7a3-bda9-4f99-8776-9bcf59c84f75,Microsoft Insider Risk Management +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INSIDER_RISK_MANAGEMENT,9d0c4ee5-e4a1-4625-ab39-d82b619b1a34,Microsoft Insider Risk Management - Exchange Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,KAIZALA_STANDALONE,0898bdbb-73b0-471a-81e5-20f1fe4dd66e,Microsoft Kaizala Pro +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MICROSOFT_LOOP,c4b8c31a-fb44-4c65-9837-a21f55fcabda,Microsoft Loop Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ML_CLASSIFICATION,d2d51368-76c9-4317-ada2-a12c004c432f,Microsoft ML-Based Classification Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,EXCHANGE_ANALYTICS,34c0d7a0-a70f-4668-9238-47f9fc208882,Microsoft MyAnalytics (Full) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner @@ -1091,8 +1117,10 @@ Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,BI_AZURE_P2,70d33638-9c74-4d01-bfd3-562de28bd4ba,Power BI Pro Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,PREMIUM_ENCRYPTION,617b097b-4b93-4ede-83de-5f075bb5fb2f,Premium Encryption in Office 365 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,PROJECT_O365_P3,b21a6b06-1988-436e-a07b-51ec6d9f52ad,Project for Office (Plan E5) +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,PURVIEW_DISCOVERY,c948ea65-2053-4a5a-8a62-9eaaaf11b522,Purview Discovery +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,Bing_Chat_Enterprise,0d0c0d31-fae7-41f2-b909-eaf4d7f26dba,RETIRED - Commercial data protection for Microsoft Copilot Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,COMMUNICATIONS_COMPLIANCE,41fcdd7d-4733-4863-9cf4-c65b83ce2df4,RETIRED - Microsoft Communications Compliance -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INSIDER_RISK_MANAGEMENT,9d0c4ee5-e4a1-4625-ab39-d82b619b1a34,RETIRED - Microsoft Insider Risk Management +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,DATA_INVESTIGATIONS,46129a58-a698-46f0-aa5b-17f6586297d9,Retired - Microsoft Data Investigations Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,SCHOOL_DATA_SYNC_P2,500b6a2a-7a50-4f40-b5f9-160e5b8c2f48,School Data Sync (Plan 2) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,SHAREPOINTENTERPRISE_EDU,63038b2c-28d0-45f6-bc36-33062963b498,SharePoint (Plan 2) for Education Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) @@ -1105,18 +1133,20 @@ Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,UNIVERSAL_PRINT_01,795f6fe0-cc4d-4773-b050-5dde4dc704c9,Universal Print Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,Virtualization Rights for Windows 10 (E3/E5+VDA),e7c91390-7625-45be-94e0-e16907e03118,Windows 10/11 Enterprise Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,WINDOWSUPDATEFORBUSINESS_DEPLOYMENTSERVICE,7bf960f6-2cd9-443a-8046-5dbff9558365,Windows Update for Business Deployment Service -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_PREMIUM_P2,eec0eb4f-6444-4f95-aba0-50c24d67f998,Microsoft Entra ID P2 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,RMS_S_PREMIUM,6c57d4b6-3b23-47a5-9bc9-69f17b4947b3,Azure Information Protection Premium P1 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,RMS_S_PREMIUM2,5689bec4-755d-4753-8b61-40975025187c,Azure Information Protection Premium P2 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,DYN365_CDS_O365_P3,28b0fa46-c39a-4188-89e2-58e979a6b014,Common Data Service +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,Intune_ServiceNow,3eeb8536-fecf-41bf-a3f8-d6f17a9f3efc,Intune ServiceNow Integration Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MFA_PREMIUM,8a256a2b-b617-496d-b51b-e76466e88db0,Microsoft Azure Multi-Factor Authentication Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ADALLOM_S_STANDALONE,2e2ddb96-6af9-4b1d-a3f0-d6ecfd22edb2,Microsoft Defender for Cloud Apps Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ATA,14ab5db5-e6c4-4b20-b4bc-13e36fd2227f,Microsoft Defender for Identity -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune for Education +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_PREMIUM_P2,eec0eb4f-6444-4f95-aba0-50c24d67f998,Microsoft Entra ID P2 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune Plan 1 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune Plan 1 for Education Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,FLOW_O365_P3,07699545-9485-468e-95b6-2fca3738be01,Power Automate for Office 365 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,POWER_VIRTUAL_AGENTS_O365_P3,ded3d325-1bdc-453e-8432-5bac26d7a014,Power Virtual Agents for Office 365 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,REMOTE_HELP,a4c6cf29-1168-4076-ba5c-e8fe0e62b17e,Remote help Microsoft 365 A5 for students use benefit,M365EDU_A5_STUUSEBNFT,31d57bc7-3a05-4867-ab53-97a17835a411,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education Microsoft 365 A5 for students use benefit,M365EDU_A5_STUUSEBNFT,31d57bc7-3a05-4867-ab53-97a17835a411,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management Microsoft 365 A5 for students use benefit,M365EDU_A5_STUUSEBNFT,31d57bc7-3a05-4867-ab53-97a17835a411,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics @@ -3633,13 +3663,19 @@ Microsoft Dynamics CRM Online,CRMSTANDARD,d17b27af-3f49-4822-99f9-56a661538792,M Microsoft Dynamics CRM Online,CRMSTANDARD,d17b27af-3f49-4822-99f9-56a661538792,NBPROFESSIONALFORCRM,3e58e97c-9abe-ebab-cd5f-d543d1529634,MICROSOFT SOCIAL ENGAGEMENT PROFESSIONAL - ELIGIBILITY CRITERIA APPLY Microsoft Dynamics CRM Online,CRMSTANDARD,d17b27af-3f49-4822-99f9-56a661538792,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,POWERAPPS FOR DYNAMICS 365 Microsoft Entra ID Governance,Microsoft_Entra_ID_Governance,cf6b0d46-4093-4546-a0ab-0b1546dcc10e,Entra_Identity_Governance,e866a266-3cff-43a3-acca-0c90a7e00c8b,Entra Identity Governance +Microsoft Entra Suite Add-on for Microsoft Entra ID P2,Microsoft_Entra_Suite_Step_Up_for_Microsoft_Entra_ID_P2,2ef3064c-c95c-426c-96dd-9ffeaa2f2c37,Entra_Premium_Internet_Access,8d23cb83-ab07-418f-8517-d7aca77307dc,Microsoft Entra Internet Access +Microsoft Entra Suite Add-on for Microsoft Entra ID P2,Microsoft_Entra_Suite_Step_Up_for_Microsoft_Entra_ID_P2,2ef3064c-c95c-426c-96dd-9ffeaa2f2c37,Entra_Premium_Private_Access,f057aab1-b184-49b2-85c0-881b02a405c5,Microsoft Entra Private Access +Microsoft Entra Suite Add-on for Microsoft Entra ID P2,Microsoft_Entra_Suite_Step_Up_for_Microsoft_Entra_ID_P2,2ef3064c-c95c-426c-96dd-9ffeaa2f2c37,Verifiable_Credentials_Service_Request,aae826b7-14cd-4691-8178-2b312f7072ea,Verifiable Credentials Service Request +Microsoft Entra Suite Add-on for Microsoft Entra ID P2,Microsoft_Entra_Suite_Step_Up_for_Microsoft_Entra_ID_P2,2ef3064c-c95c-426c-96dd-9ffeaa2f2c37,Entra_Identity_Governance,e866a266-3cff-43a3-acca-0c90a7e00c8b,Entra Identity Governance Microsoft Fabric (Free),POWER_BI_STANDARD,a403ebcc-fae0-4ca2-8c8c-7a907fd6c235,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Microsoft Fabric (Free),POWER_BI_STANDARD,a403ebcc-fae0-4ca2-8c8c-7a907fd6c235,BI_AZURE_P0,2049e525-b859-401b-b2a0-e0a31c4b1fe4,Power BI (free) +Microsoft Fabric (Free),POWER_BI_STANDARD,a403ebcc-fae0-4ca2-8c8c-7a907fd6c235,PURVIEW_DISCOVERY,c948ea65-2053-4a5a-8a62-9eaaaf11b522,Purview Discovery Microsoft Fabric (Free) for faculty,POWER_BI_STANDARD_FACULTY,ade29b5f-397e-4eb9-a287-0344bd46c68d,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,EXCHANGE_S_FOUNDATION Microsoft Fabric (Free) for faculty,POWER_BI_STANDARD_FACULTY,ade29b5f-397e-4eb9-a287-0344bd46c68d,BI_AZURE_P0,2049e525-b859-401b-b2a0-e0a31c4b1fe4,BI_AZURE_P0 Microsoft Fabric (Free) for student,POWER_BI_STANDARD_STUDENT,bdcaf6aa-04c1-4b8f-b64e-6e3bd505ac64,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,EXCHANGE_S_FOUNDATION Microsoft Fabric (Free) for student,POWER_BI_STANDARD_STUDENT,bdcaf6aa-04c1-4b8f-b64e-6e3bd505ac64,BI_AZURE_P0,2049e525-b859-401b-b2a0-e0a31c4b1fe4,BI_AZURE_P0 Microsoft Imagine Academy,IT_ACADEMY_AD,ba9a34de-4489-469d-879c-0f0f145321cd,IT_ACADEMY_AD,d736def0-1fde-43f0-a5be-e3f8b2de6e41,MS IMAGINE ACADEMY +Microsoft Intune Advanced Analytics,Microsoft_Intune_Advanced_Analytics,5e36d0d4-e9e5-4052-aba0-0257465c9b86,Intune_AdvancedEA,2a4baa0e-5e99-4c38-b1f2-6864960f1bd1,Microsoft Intune Advanced Analytics Microsoft Intune Device,INTUNE_A_D,2b317a4a-77a6-4188-9437-b68a77b4e2c6,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Microsoft Intune Device,INTUNE_A_D,2b317a4a-77a6-4188-9437-b68a77b4e2c6,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune Microsoft Intune Device for Government,INTUNE_A_D_GOV,2c21e77a-e0d6-4570-b38a-7ff2dc17d2ca,EXCHANGE_S_FOUNDATION_GOV,922ba911-5694-4e99-a794-73aed9bfeec8,Exchange Foundation for Government @@ -3696,6 +3732,10 @@ Microsoft Stream Storage Add-On (500 GB),STREAM_STORAGE,9bd7c846-9556-4453-a542- Microsoft Sustainability Manager Premium,Microsoft_Sustainability_Manager_Premium,aecb477b-2f56-4e38-b711-b752c24fc19b,CDS_CLOUD_FOR_SUSTAINABILITY_PLUS,ba80223c-e515-4642-a838-3e7d66f70cb6,Common Data Services for Cloud for Sustainability Plus Microsoft Sustainability Manager Premium,Microsoft_Sustainability_Manager_Premium,aecb477b-2f56-4e38-b711-b752c24fc19b,MCS_BIZAPPS_CLOUD_FOR_SUSTAINABILITY_PLUS,ed29ae92-ff5f-4446-8460-83c54d0e7088,MCS - BizApps Cloud for Sustainability Plus Microsoft Sustainability Manager Premium,Microsoft_Sustainability_Manager_Premium,aecb477b-2f56-4e38-b711-b752c24fc19b,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +Microsoft Sustainability Manager Premium USL Plus,MICROSOFT_SUSTAINABILITY_MANAGER_PREMIUM_USL_ADDON,9d576ffb-dd32-4c33-91ee-91625b61424a,MCS_BIZAPPS_CLOUD_FOR_SUSTAINABILITY_USL_PLUS,beaf5b5c-d11c-4417-b5cb-cd9f9e6719b0,MCS - BizApps Cloud for Sustainability USL Plus +Microsoft Sustainability Manager Premium USL Plus,MICROSOFT_SUSTAINABILITY_MANAGER_PREMIUM_USL_ADDON,9d576ffb-dd32-4c33-91ee-91625b61424a,POWER_APPS_FOR_MCS_USL_PLUS,c5502fe7-406d-442a-827f-4948b821ba08,Power Apps for Cloud for Sustainability USL Plus +Microsoft Sustainability Manager Premium USL Plus,MICROSOFT_SUSTAINABILITY_MANAGER_PREMIUM_USL_ADDON,9d576ffb-dd32-4c33-91ee-91625b61424a,POWER_AUTOMATE_FOR_MCS_USL_PLUS,1c22bb50-96fb-49e5-baa6-195cab19eee2,Power Automate for Cloud for Sustainability USL Plus +Microsoft Sustainability Manager Premium USL Plus,MICROSOFT_SUSTAINABILITY_MANAGER_PREMIUM_USL_ADDON,9d576ffb-dd32-4c33-91ee-91625b61424a,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Microsoft Sustainability Manager USL Essentials,Microsoft_Cloud_for_Sustainability_USL,ece037b4-a52b-4cf8-93ea-649e5d83767a,MCS_BizApps_Cloud_for_Sustainability_USL,c46c42af-d654-4385-8c85-29a84f3dfb22,MCS - BizApps - Cloud for Sustainability USL Microsoft Sustainability Manager USL Essentials,Microsoft_Cloud_for_Sustainability_USL,ece037b4-a52b-4cf8-93ea-649e5d83767a,POWER_APPS_FOR_MCS_USL,5ffd371c-037a-41a2-98a3-6452f8c5de17,Power Apps for Cloud for Sustainability USL Microsoft Sustainability Manager USL Essentials,Microsoft_Cloud_for_Sustainability_USL,ece037b4-a52b-4cf8-93ea-649e5d83767a,POWER_AUTOMATE_FOR_MCS_USL,ccbe468e-7973-442c-8ec4-5fbe16438711,Power Automate for Cloud for Sustainability USL @@ -3808,18 +3848,20 @@ Microsoft Teams Rooms Pro,Microsoft_Teams_Rooms_Pro,4cde982a-ede4-4409-9ae6-b003 Microsoft Teams Rooms Pro,Microsoft_Teams_Rooms_Pro,4cde982a-ede4-4409-9ae6-b003453c8ea6,TEAMS1,57ff2da0-773e-42df-b2af-ffb7a2317929,Microsoft Teams Microsoft Teams Rooms Pro,Microsoft_Teams_Rooms_Pro,4cde982a-ede4-4409-9ae6-b003453c8ea6,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) Microsoft Teams Rooms Pro,Microsoft_Teams_Rooms_Pro,4cde982a-ede4-4409-9ae6-b003453c8ea6,WHITEBOARD_PLAN3,4a51bca5-1eff-43f5-878c-177680f191af,Whiteboard (Plan 3) -Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education +Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,TEAMS1,57ff2da0-773e-42df-b2af-ffb7a2317929,Microsoft Teams Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,MTRProManagement,ecc74eae-eeb7-4ad5-9c88-e8b2bfca75b8,Microsoft Teams Rooms Pro Management Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) +Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,Teams_Rooms_Pro,0374d34c-6be4-4dbb-b3f0-26105db0b28a,Teams Rooms Pro Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,Teams_Room_Basic,8081ca9c-188c-4b49-a8e5-c23b5e9463a8,Teams Rooms Test 1 Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,Teams_Room_Pro,ec17f317-f4bc-451e-b2da-0167e5c260f9,Teams Rooms Test 2 Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,WHITEBOARD_PLAN3,4a51bca5-1eff-43f5-878c-177680f191af,Whiteboard (Plan 3) Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,WINDEFATP,871d91ec-ec1a-452b-a83f-bd76c7d770ef,Microsoft Defender for Endpoint Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune Plan 1 +Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,SPECIALTY_DEVICES,cfce7ae3-4b41-4438-999c-c0e91f3b7fb9,Specialty devices Microsoft Teams Rooms Pro for GCC,Microsoft_Teams_Rooms_Pro_GCC,31ecb341-2a17-483e-9140-c473006d1e1a,MCOMEETADV_GOV,f544b08d-1645-4287-82de-8d91f37c02a1,Microsoft 365 Audio Conferencing for Government Microsoft Teams Rooms Pro for GCC,Microsoft_Teams_Rooms_Pro_GCC,31ecb341-2a17-483e-9140-c473006d1e1a,MCOEV_GOV,db23fce2-a974-42ef-9002-d78dd42a0f22,Microsoft 365 Phone System for Government Microsoft Teams Rooms Pro for GCC,Microsoft_Teams_Rooms_Pro_GCC,31ecb341-2a17-483e-9140-c473006d1e1a,TEAMS_GOV,304767db-7d23-49e8-a945-4a7eb65f9f28,Microsoft Teams for Government @@ -3914,14 +3956,14 @@ Office 365 Multi-Geo Capabilities,OFFICE365_MULTIGEO,84951599-62b7-46f3-9c9d-305 Office 365 Multi-Geo Capabilities,OFFICE365_MULTIGEO,84951599-62b7-46f3-9c9d-30551b2ad607,TEAMSMULTIGEO,41eda15d-6b52-453b-906f-bc4a5b25a26b,Teams Multi-Geo Nonprofit Portal,NONPROFIT_PORTAL,aa2695c9-8d59-4800-9dc8-12e01f1735af,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Nonprofit Portal,NONPROFIT_PORTAL,aa2695c9-8d59-4800-9dc8-12e01f1735af,NONPROFIT_PORTAL,7dbc2d88-20e2-4eb6-b065-4510b38d6eb2,Nonprofit Portal -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service - O365 P1 +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,EXCHANGE_S_STANDARD,9aaf7827-d63c-4b61-89c3-182f06f82e5c,Exchange Online (Plan 1) Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Microsoft Microsoft Entra Rights +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,OFFICE_FORMS_PLAN_2,9b5de886-f035-4ff2-b3d8-c9127bea3620,Microsoft Forms (Plan 2) -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,KAIZALA_O365_P2,54fc630f-5a40-48ee-8965-af0503c1386e,Microsoft Kaizala Pro Plan 2 +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,KAIZALA_O365_P2,54fc630f-5a40-48ee-8965-af0503c1386e,Microsoft Kaizala Pro Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,MICROSOFT_SEARCH,94065c59-bc8e-4e8b-89e5-5138d471eaff,Microsoft Search Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,Deskless,8c7d2df8-86f0-4902-b2ed-a0458298f3b3,Microsoft StaffHub @@ -3931,9 +3973,8 @@ Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c897 Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,Nucleus,db4d623d-b514-490b-b7ef-8885eee514de,Nucleus Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,SHAREPOINTWAC_EDU,e03c7e47-402c-463c-ab25-949079bedb21,Office for the Web for Education Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,OFFICEMOBILE_SUBSCRIPTION,c63d4d19-e8cb-460e-b37c-4d6c34603745,Office Mobile Apps for Office 365 -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,PROJECT_O365_P1,a55dfd10-0864-46d9-a3cd-da5991a3e0e2,Project for Office (Plan E1) +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,Bing_Chat_Enterprise,0d0c0d31-fae7-41f2-b909-eaf4d7f26dba,RETIRED - Commercial data protection for Microsoft Copilot Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,SCHOOL_DATA_SYNC_P1,c33802dd-1b50-4b9a-8bb9-f13d2cdeadac,School Data Sync (Plan 1) Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,SHAREPOINTSTANDARD_EDU,0a4983bb-d3e5-4a09-95d8-b2d0127b3df5,SharePoint (Plan 1) for Education Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) @@ -3942,6 +3983,9 @@ Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c897 Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,VIVA_LEARNING_SEEDED,b76fb638-6ba6-402a-b9f9-83d28acb3d86,Viva Learning Seeded Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,WHITEBOARD_PLAN1,b8afc642-032e-4de5-8c0a-507a7bba7e5d,Whiteboard (Plan 1) Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service - O365 P1 Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics @@ -3969,14 +4013,14 @@ Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-89 Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,VIVA_LEARNING_SEEDED,b76fb638-6ba6-402a-b9f9-83d28acb3d86,Viva Learning Seeded Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,WHITEBOARD_PLAN1,b8afc642-032e-4de5-8c0a-507a7bba7e5d,Whiteboard (Plan 1) Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service - O365 P1 +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,EXCHANGE_S_STANDARD,9aaf7827-d63c-4b61-89c3-182f06f82e5c,Exchange Online (Plan 1) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Microsoft Microsoft Entra Rights +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,OFFICE_FORMS_PLAN_2,9b5de886-f035-4ff2-b3d8-c9127bea3620,Microsoft Forms (Plan 2) -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,KAIZALA_O365_P2,54fc630f-5a40-48ee-8965-af0503c1386e,Microsoft Kaizala Pro Plan 2 +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,KAIZALA_O365_P2,54fc630f-5a40-48ee-8965-af0503c1386e,Microsoft Kaizala Pro Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,MICROSOFT_SEARCH,94065c59-bc8e-4e8b-89e5-5138d471eaff,Microsoft Search Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,Deskless,8c7d2df8-86f0-4902-b2ed-a0458298f3b3,Microsoft StaffHub @@ -3985,9 +4029,8 @@ Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4 Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,INTUNE_O365,882e1d05-acd1-4ccb-8708-6ee03664b117,Mobile Device Management for Office 365 Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,SHAREPOINTWAC_EDU,e03c7e47-402c-463c-ab25-949079bedb21,Office for the Web for Education Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,OFFICEMOBILE_SUBSCRIPTION,c63d4d19-e8cb-460e-b37c-4d6c34603745,Office Mobile Apps for Office 365 -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,PROJECT_O365_P1,a55dfd10-0864-46d9-a3cd-da5991a3e0e2,Project for Office (Plan E1) +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,Bing_Chat_Enterprise,0d0c0d31-fae7-41f2-b909-eaf4d7f26dba,RETIRED - Commercial data protection for Microsoft Copilot Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,SCHOOL_DATA_SYNC_P1,c33802dd-1b50-4b9a-8bb9-f13d2cdeadac,School Data Sync (Plan 1) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,SHAREPOINTSTANDARD_EDU,0a4983bb-d3e5-4a09-95d8-b2d0127b3df5,SharePoint (Plan 1) for Education Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) @@ -3995,6 +4038,9 @@ Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4 Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,BPOS_S_TODO_2,c87f142c-d1e9-4363-8630-aaea9c4d9ae5,To-Do (Plan 2) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,WHITEBOARD_PLAN1,b8afc642-032e-4de5-8c0a-507a7bba7e5d,Whiteboard (Plan 1) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 Office 365 A1 Plus for students,STANDARDWOFFPACK_IW_STUDENT,e82ae690-a2d5-4d76-8d30-7c6e01e6022e,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education Office 365 A1 Plus for students,STANDARDWOFFPACK_IW_STUDENT,e82ae690-a2d5-4d76-8d30-7c6e01e6022e,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service - O365 P1 Office 365 A1 Plus for students,STANDARDWOFFPACK_IW_STUDENT,e82ae690-a2d5-4d76-8d30-7c6e01e6022e,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics @@ -5059,8 +5105,11 @@ Power Apps Per User BD Only,POWERAPPS_PER_USER_BD_ONLY,2ced8a00-3ed1-4295-ab7c-5 Power Apps Per User BD Only,POWERAPPS_PER_USER_BD_ONLY,2ced8a00-3ed1-4295-ab7c-57170ff28e58,CDS_ POWERAPPS_PER_USER_CUSTOM,2e8dde43-6986-479d-b179-7dbe31c31f60,CDS Power Apps Per User Custom Power Apps Per User BD Only,POWERAPPS_PER_USER_BD_ONLY,2ced8a00-3ed1-4295-ab7c-57170ff28e58,POWERAPPS_PER_USER,ea2cf03b-ac60-46ae-9c1d-eeaeb63cec86,Power Apps per User Plan Power Apps Per User BD Only,POWERAPPS_PER_USER_BD_ONLY,2ced8a00-3ed1-4295-ab7c-57170ff28e58,Flow_PowerApps_PerUser,dc789ed8-0170-4b65-a415-eb77d5bb350a,Power Automate for Power Apps per User Plan -Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,DYN365_CDS_P2,6ea4c1ef-c259-46df-bce2-943342cd3cb2,Common Data Service - P2 +Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,CDSAICAPACITY_PERUSER_NEW,74d93933-6f22-436e-9441-66d205435abb,AI Builder capacity Per User add-on +Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,DYN365_CDS_P2,6ea4c1ef-c259-46df-bce2-943342cd3cb2,Common Data Service +Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,CDSAICAPACITY_PERUSER,91f50f7b-2204-4803-acac-5cf5668b8b39,DO NOT USE - AI Builder capacity Per User add-on Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,POWERAPPS_PER_USER,ea2cf03b-ac60-46ae-9c1d-eeaeb63cec86,Power Apps per User Plan Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,Flow_PowerApps_PerUser,dc789ed8-0170-4b65-a415-eb77d5bb350a,Power Automate for Power Apps per User Plan Power Apps Premium for Government,POWERAPPS_PER_USER_GCC,8e4c6baa-f2ff-4884-9c38-93785d0d7ba1,CDSAICAPACITY_PERUSER,91f50f7b-2204-4803-acac-5cf5668b8b39,AI Builder capacity Per User add-on @@ -5130,6 +5179,8 @@ Power BI Premium Per User,PBI_PREMIUM_PER_USER,c1d032e0-5619-4761-9b5c-75b6831e1 Power BI Premium Per User,PBI_PREMIUM_PER_USER,c1d032e0-5619-4761-9b5c-75b6831e1711,BI_AZURE_P3,0bf3c642-7bb5-4ccc-884e-59d09df0266c,Power BI Premium Per User Power BI Premium Per User,PBI_PREMIUM_PER_USER,c1d032e0-5619-4761-9b5c-75b6831e1711,BI_AZURE_P2,70d33638-9c74-4d01-bfd3-562de28bd4ba,Power BI Pro Power BI Premium Per User Add-On,PBI_PREMIUM_PER_USER_ADDON,de376a03-6e5b-42ec-855f-093fb50b8ca5,BI_AZURE_P3,0bf3c642-7bb5-4ccc-884e-59d09df0266c,Power BI Premium Per User +Power BI Premium Per User Add-On for Faculty,PBI_PREMIUM_PER_USER_ADDON_FACULTY,c05b235f-be75-4029-8851-6a4170758eef,BI_AZURE_P3,0bf3c642-7bb5-4ccc-884e-59d09df0266c,Power BI Premium Per User +Power BI Premium Per User Add-On for Faculty,PBI_PREMIUM_PER_USER_ADDON_FACULTY,c05b235f-be75-4029-8851-6a4170758eef,PURVIEW_DISCOVERY,c948ea65-2053-4a5a-8a62-9eaaaf11b522,Purview Discovery Power BI Premium Per User Add-On for GCC,PBI_PREMIUM_PER_USER_ADDON_CE_GCC,66024bbf-4cd4-4329-95c8-c932e2ae01a8,BI_AZURE_P3_GOV,32d15238-9a8c-46da-af3f-21fc5351d365,Power BI Premium Per User for Government Power BI Premium Per User Add-On for GCC,PBI_PREMIUM_PER_USER_ADDON_GCC,1b572d5e-1bf8-4b19-9259-f9eda31a6972,BI_AZURE_P3_GOV,32d15238-9a8c-46da-af3f-21fc5351d365,Power BI Premium Per User for Government Power BI Premium Per User Dept,PBI_PREMIUM_PER_USER_DEPT,f168a3fb-7bcf-4a27-98c3-c235ea4b78b4,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation @@ -5426,6 +5477,14 @@ Teams Premium (for Departments),Teams_Premium_(for_Departments),52ea0e27-ae73-49 Teams Premium (for Departments),Teams_Premium_(for_Departments),52ea0e27-ae73-4983-a08f-13561ebdb823,TEAMSPRO_VIRTUALAPPT,9104f592-f2a7-4f77-904c-ca5a5715883f,Microsoft Teams Premium Virtual Appointment Teams Premium (for Departments),Teams_Premium_(for_Departments),52ea0e27-ae73-4983-a08f-13561ebdb823,MCO_VIRTUAL_APPT,711413d0-b36e-4cd4-93db-0a50a4ab7ea3,Microsoft Teams Premium Virtual Appointments Teams Premium (for Departments),Teams_Premium_(for_Departments),52ea0e27-ae73-4983-a08f-13561ebdb823,TEAMSPRO_WEBINAR,78b58230-ec7e-4309-913c-93a45cc4735b,Microsoft Teams Premium Webinar +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,MICROSOFT_ECDN,85704d55-2e73-47ee-93b4-4b8ea14db92b,Microsoft eCDN +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_MGMT,0504111f-feb8-4a3c-992a-70280f9a2869,Microsoft Teams Premium Intelligent +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_CUST,cc8c0802-a325-43df-8cba-995d0c6cb373,Microsoft Teams Premium Personalized +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_PROTECTION,f8b44f54-18bb-46a3-9658-44ab58712968,Microsoft Teams Premium Secure +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_VIRTUALAPPT,9104f592-f2a7-4f77-904c-ca5a5715883f,Microsoft Teams Premium Virtual Appointment +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,MCO_VIRTUAL_APPT,711413d0-b36e-4cd4-93db-0a50a4ab7ea3,Microsoft Teams Premium Virtual Appointments +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_WEBINAR,78b58230-ec7e-4309-913c-93a45cc4735b,Microsoft Teams Premium Webinar +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,QUEUES_APP,ab2d4fb5-f80a-4bf1-a11d-7f1da254041b,Queues app for Microsoft Teams Teams Rooms Premium,MTR_PREM,4fb214cb-a430-4a91-9c91-4976763aa78f,MMR_P1,bdaa59a3-74fd-4137-981a-31d4f84eb8a0,Meeting Room Managed Services Teams Rooms Premium,MTR_PREM,4fb214cb-a430-4a91-9c91-4976763aa78f,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing Teams Rooms Premium,MTR_PREM,4fb214cb-a430-4a91-9c91-4976763aa78f,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecAppApprovalTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecAppApprovalTemplate.ps1 index 5c55136cccaf..acde7892b480 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecAppApprovalTemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecAppApprovalTemplate.ps1 @@ -13,16 +13,127 @@ function Push-ExecAppApprovalTemplate { return } - $ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -tenantid $Item.Tenant - if ($Item.AppId -notin $ServicePrincipalList.appId) { - Write-Information "Adding $($Item.AppId) to tenant $($Item.Tenant)." - $PostResults = New-GraphPostRequest 'https://graph.microsoft.com/beta/servicePrincipals' -type POST -tenantid $Item.tenant -body "{ `"appId`": `"$($Item.appId)`" }" - Write-LogMessage -message "Added $($Item.AppId) to tenant $($Item.Tenant)" -tenant $Item.Tenant -API 'Add Multitenant App' -sev Info + # Get the template data to determine if it's a Gallery Template or Enterprise App + $Table = Get-CIPPTable -TableName 'templates' + $Template = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq 'AppApprovalTemplate' and RowKey eq '$TemplateId'" + + if (!$Template) { + Write-LogMessage -message "Template $TemplateId not found" -tenant $Item.Tenant -API 'Add Multitenant App' -sev Error + return + } + + $TemplateData = $Template.JSON | ConvertFrom-Json + # Default to EnterpriseApp for backward compatibility with older templates + $AppType = $TemplateData.AppType + if (-not $AppType) { + $AppType = 'EnterpriseApp' + } + + # Handle Gallery Templates + if ($AppType -eq 'GalleryTemplate') { + Write-Information "Deploying Gallery Template $($TemplateData.AppName) to tenant $($Item.Tenant)." + + # Use the Gallery Template instantiation API + $GalleryTemplateId = $TemplateData.GalleryTemplateId + if (!$GalleryTemplateId) { + Write-LogMessage -message 'Gallery Template ID not found in template data' -tenant $Item.Tenant -API 'Add Multitenant App' -sev Error + return + } + + # Check if the app already exists in the tenant + $ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -tenantid $Item.Tenant + if ($TemplateData.GalleryTemplateId -in $ServicePrincipalList.applicationTemplateId) { + Write-LogMessage -message "Gallery Template app $($TemplateData.AppName) already exists in tenant $($Item.Tenant)" -tenant $Item.Tenant -API 'Add Gallery App' -sev Info + return + } + + # Instantiate the gallery template + $InstantiateBody = @{ + displayName = $TemplateData.AppName + } | ConvertTo-Json -Depth 10 + + $InstantiateResult = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/applicationTemplates/$GalleryTemplateId/instantiate" -type POST -tenantid $Item.tenant -body $InstantiateBody + + if ($InstantiateResult.application.appId) { + Write-LogMessage -message "Successfully deployed Gallery Template $($TemplateData.AppName) to tenant $($Item.Tenant). Application ID: $($InstantiateResult.application.appId)" -tenant $Item.Tenant -API 'Add Gallery App' -sev Info + # Get application registration + $App = $InstantiateResult.application.appId + $Application = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/applications(appId='$App')" -tenantid $Item.tenant -AsApp $true + if ($Application.requiredResourceAccess) { + Add-CIPPDelegatedPermission -RequiredResourceAccess $Application.requiredResourceAccess -ApplicationId $App -Tenantfilter $Item.Tenant + Add-CIPPApplicationPermission -RequiredResourceAccess $Application.requiredResourceAccess -ApplicationId $App -Tenantfilter $Item.Tenant + } + } else { + Write-LogMessage -message "Gallery Template deployment completed but application ID not returned for $($TemplateData.AppName) in tenant $($Item.Tenant)" -tenant $Item.Tenant -API 'Add Gallery App' -sev Warning + } + + } elseif ($AppType -eq 'ApplicationManifest') { + Write-Information "Deploying Application Manifest $($TemplateData.AppName) to tenant $($Item.Tenant)." + + # Get the application manifest from template data + $ApplicationManifest = $TemplateData.ApplicationManifest + if (!$ApplicationManifest) { + Write-LogMessage -message 'Application Manifest not found in template data' -tenant $Item.Tenant -API 'Add Multitenant App' -sev Error + return + } + + # Check for existing application by display name + $ExistingApp = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/applications?`$filter=displayName eq '$($TemplateData.AppName)'&`$top=1" -tenantid $Item.Tenant -NoAuthCheck $true + if ($ExistingApp -and $ExistingApp.value) { + Write-LogMessage -message "Application Manifest $($TemplateData.AppName) already exists in tenant $($Item.Tenant)" -tenant $Item.Tenant -API 'Add App Manifest' -sev Info + return + } + + $PropertiesToRemove = @('appId', 'id', 'createdDateTime', 'publisherDomain', 'servicePrincipalLockConfiguration', 'identifierUris', 'applicationIdUris') + + # Strip tenant-specific data that might cause conflicts + $CleanManifest = $ApplicationManifest | ConvertTo-Json -Depth 10 | ConvertFrom-Json + foreach ($Property in $PropertiesToRemove) { + $CleanManifest.PSObject.Properties.Remove($Property) + } + + # Create the application from manifest + try { + $CreateBody = $CleanManifest | ConvertTo-Json -Depth 10 + $CreatedApp = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/applications' -type POST -tenantid $Item.tenant -body $CreateBody + + if ($CreatedApp.appId) { + # Create service principal for the application + $ServicePrincipalBody = @{ + appId = $CreatedApp.appId + } | ConvertTo-Json + + $ServicePrincipal = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/servicePrincipals' -type POST -tenantid $Item.tenant -body $ServicePrincipalBody + + Write-LogMessage -message "Successfully deployed Application Manifest $($TemplateData.AppName) to tenant $($Item.Tenant). Application ID: $($CreatedApp.appId)" -tenant $Item.Tenant -API 'Add App Manifest' -sev Info + $DelegateResourceAccess = $ApplicationManifest.requiredResourceAccess + $ApplicationResourceAccess = $ApplicationManifest.requiredResourceAccess + if ($ApplicationManifest.requiredResourceAccess) { + Add-CIPPDelegatedPermission -RequiredResourceAccess $ApplicationManifest.requiredResourceAccess -ApplicationId $App -Tenantfilter $Tenant + Add-CIPPApplicationPermission -RequiredResourceAccess $ApplicationManifest.requiredResourceAccess -ApplicationId $App -Tenantfilter $Tenant + } + + } else { + Write-LogMessage -message "Application Manifest deployment failed - no application ID returned for $($TemplateData.AppName) in tenant $($Item.Tenant)" -tenant $Item.Tenant -API 'Add App Manifest' -sev Error + } + } catch { + Write-LogMessage -message "Error creating application from manifest in tenant $($Item.Tenant) - $($_.Exception.Message)" -tenant $Item.Tenant -API 'Add App Manifest' -sev Error + throw + } + } else { - Write-LogMessage -message "This app already exists in tenant $($Item.Tenant). We're adding the required permissions." -tenant $Item.Tenant -API 'Add Multitenant App' -sev Info + # Handle Enterprise Apps (existing logic) + $ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -tenantid $Item.Tenant + if ($Item.AppId -notin $ServicePrincipalList.appId) { + Write-Information "Adding $($Item.AppId) to tenant $($Item.Tenant)." + $PostResults = New-GraphPostRequest 'https://graph.microsoft.com/beta/servicePrincipals' -type POST -tenantid $Item.tenant -body "{ `"appId`": `"$($Item.appId)`" }" + Write-LogMessage -message "Added $($Item.AppId) to tenant $($Item.Tenant)" -tenant $Item.Tenant -API 'Add Multitenant App' -sev Info + } else { + Write-LogMessage -message "This app already exists in tenant $($Item.Tenant). We're adding the required permissions." -tenant $Item.Tenant -API 'Add Multitenant App' -sev Info + } + Add-CIPPApplicationPermission -TemplateId $TemplateId -Tenantfilter $Item.Tenant + Add-CIPPDelegatedPermission -TemplateId $TemplateId -Tenantfilter $Item.Tenant } - Add-CIPPApplicationPermission -TemplateId $TemplateId -Tenantfilter $Item.Tenant - Add-CIPPDelegatedPermission -TemplateId $TemplateId -Tenantfilter $Item.Tenant } catch { Write-LogMessage -message "Error adding application to tenant $($Item.Tenant) - $($_.Exception.Message)" -tenant $Item.Tenant -API 'Add Multitenant App' -sev Error Write-Error $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 index bafe1e39fa59..3ed8752ba62d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecScheduledCommand.ps1 @@ -10,7 +10,12 @@ function Push-ExecScheduledCommand { $Table = Get-CippTable -tablename 'ScheduledTasks' $task = $Item.TaskInfo $commandParameters = $Item.Parameters | ConvertTo-Json -Depth 10 | ConvertFrom-Json -AsHashtable + + # Handle tenant resolution - support both direct tenant and group-expanded tenants $Tenant = $Item.Parameters.TenantFilter ?? $Item.TaskInfo.Tenant + + # For tenant group tasks, the tenant will be the expanded tenant from the orchestrator + # We don't need to expand groups here as that's handled in the orchestrator $TenantInfo = Get-Tenants -TenantFilter $Tenant $null = Update-AzDataTableEntity -Force @Table -Entity @{ @@ -57,6 +62,7 @@ function Push-ExecScheduledCommand { $results = & $Item.Command @commandParameters } catch { $results = "Task Failed: $($_.Exception.Message)" + $State = 'Failed' } Write-Host 'ran the command. Processing results' @@ -68,9 +74,12 @@ function Push-ExecScheduledCommand { if ($results -is [String]) { $results = @{ Results = $results } } - if ($results -is [array] -and $results[0] -is [string]) { - $results = $results | Where-Object { $_ -is [string] } - $results = $results | ForEach-Object { @{ Results = $_ } } + if ($results -is [array] -and $results[0] -is [string] -or $results[0].resultText -is [string]) { + $results = $results | Where-Object { $_ -is [string] -or $_.resultText -is [string] } + $results = $results | ForEach-Object { + $Message = $_.resultText ?? $_ + @{ Results = $Message } + } } if ($results -is [string]) { @@ -81,14 +90,14 @@ function Push-ExecScheduledCommand { } } - if ($StoredResults.Length -gt 64000 -or $task.Tenant -eq 'AllTenants') { + if ($StoredResults.Length -gt 64000 -or $task.Tenant -eq 'AllTenants' -or $task.TenantGroup) { $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 + $null = Add-CIPPAzDataTableEntity @TaskResultsTable -Entity $TaskResults -Force $StoredResults = @{ Results = 'Completed, details are available in the More Info pane' } | ConvertTo-Json -Compress } } catch { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecEditTemplate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecEditTemplate.ps1 index b1367d6c8076..96bb985840b9 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecEditTemplate.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecEditTemplate.ps1 @@ -1,6 +1,6 @@ using namespace System.Net -Function Invoke-ExecEditTemplate { +function Invoke-ExecEditTemplate { <# .FUNCTIONALITY Entrypoint,AnyTenant @@ -16,19 +16,18 @@ Function Invoke-ExecEditTemplate { try { $Table = Get-CippTable -tablename 'templates' - $guid = $request.body.guid + $guid = $request.body.id $JSON = ConvertTo-Json -Compress -Depth 100 -InputObject ($request.body | Select-Object * -ExcludeProperty GUID) - $Type = $request.Body.Type + $Type = $request.query.Type if ($Type -eq 'IntuneTemplate') { Write-Host 'Intune Template' $OriginalTemplate = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq 'IntuneTemplate' and RowKey eq '$GUID'" $OriginalTemplate = ($OriginalTemplate.JSON | ConvertFrom-Json -Depth 100) - $RawJSON = $OriginalTemplate.RAWJson + $RawJSON = ConvertTo-Json -Compress -Depth 100 -InputObject $Request.body.parsedRAWJson Set-CIPPIntuneTemplate -RawJSON $RawJSON -GUID $GUID -DisplayName $Request.body.displayName -Description $Request.body.description -templateType $OriginalTemplate.Type -Headers $Request.Headers } else { $Table.Force = $true - Add-CIPPAzDataTableEntity @Table -Entity @{ JSON = "$JSON" RowKey = "$GUID" diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecGraphRequest.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecGraphRequest.ps1 deleted file mode 100644 index d06367943d64..000000000000 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecGraphRequest.ps1 +++ /dev/null @@ -1,112 +0,0 @@ -using namespace System.Net - -Function Invoke-ExecGraphRequest { - <# - .FUNCTIONALITY - Entrypoint - #> - [CmdletBinding()] - param($Request, $TriggerMetadata) - - $APIName = $Request.Params.CIPPEndpoint - $Headers = $Request.Headers - Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - - Function ConvertTo-FlatObject { - # https://evotec.xyz/powershell-converting-advanced-object-to-flat-object/ - MIT License - [CmdletBinding()] - Param ( - [Parameter(ValueFromPipeLine)][Object[]]$Objects, - [String]$Separator = '.', - [ValidateSet('', 0, 1)]$Base = 1, - [int]$Depth = 5, - [Parameter(DontShow)][String[]]$Path, - [Parameter(DontShow)][System.Collections.IDictionary] $OutputObject - ) - Begin { - $InputObjects = [System.Collections.Generic.List[Object]]::new() - } - Process { - foreach ($O in $Objects) { - $InputObjects.Add($O) - } - } - End { - If ($PSBoundParameters.ContainsKey('OutputObject')) { - $Object = $InputObjects[0] - $Iterate = [ordered] @{} - if ($null -eq $Object) { - #Write-Verbose -Message "ConvertTo-FlatObject - Object is null" - } elseif ($Object.GetType().Name -in 'String', 'DateTime', 'TimeSpan', 'Version', 'Enum') { - $Object = $Object.ToString() - } elseif ($Depth) { - $Depth-- - If ($Object -is [System.Collections.IDictionary]) { - $Iterate = $Object - } elseif ($Object -is [Array] -or $Object -is [System.Collections.IEnumerable]) { - $i = $Base - foreach ($Item in $Object.GetEnumerator()) { - $Iterate["$i"] = $Item - $i += 1 - } - } else { - foreach ($Prop in $Object.PSObject.Properties) { - if ($Prop.IsGettable) { - $Iterate["$($Prop.Name)"] = $Object.$($Prop.Name) - } - } - } - } - If ($Iterate.Keys.Count) { - foreach ($Key in $Iterate.Keys) { - ConvertTo-FlatObject -Objects @(, $Iterate["$Key"]) -Separator $Separator -Base $Base -Depth $Depth -Path ($Path + $Key) -OutputObject $OutputObject - } - } else { - $Property = $Path -Join $Separator - $OutputObject[$Property] = $Object - } - } elseif ($InputObjects.Count -gt 0) { - foreach ($ItemObject in $InputObjects) { - $OutputObject = [ordered]@{} - ConvertTo-FlatObject -Objects @(, $ItemObject) -Separator $Separator -Base $Base -Depth $Depth -Path $Path -OutputObject $OutputObject - [PSCustomObject] $OutputObject - } - } - } - } - $TenantFilter = $Request.Query.TenantFilter - try { - if ($TenantFilter -ne 'AllTenants') { - $RawGraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/$($Request.Query.Endpoint)" -tenantid $TenantFilter -NoPagination [boolean]$Request.query.DisablePagination -ComplexFilter - } else { - $RawGraphRequest = Get-Tenants | ForEach-Object -Parallel { - Import-Module '.\Modules\AzBobbyTables' - Import-Module '.\Modules\CIPPCore' - try { - $DefaultDomainName = $_.defaultDomainName - $TenantName = $_.displayName - New-GraphGetRequest -uri "https://graph.microsoft.com/beta/$($using:Request.Query.Endpoint)" -tenantid $DefaultDomainName -NoPagination [boolean]$using:Request.query.DisablePagination -ComplexFilter | Select-Object @{ - label = 'Tenant' - expression = { $TenantName } - }, * - } catch { - continue - } - } - - } - $GraphRequest = $RawGraphRequest | Where-Object -Property '@odata.context' -EQ $null | ConvertTo-FlatObject - $StatusCode = [HttpStatusCode]::OK - } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - $StatusCode = [HttpStatusCode]::Forbidden - $GraphRequest = $ErrorMessage - } - - # Associate values to output bindings by calling 'Push-OutputBinding'. - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = $StatusCode - Body = @($GraphRequest) - }) - -} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecServicePrincipals.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecServicePrincipals.ps1 index c0f7873d34ac..704a75cb30ad 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecServicePrincipals.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecServicePrincipals.ps1 @@ -3,7 +3,7 @@ function Invoke-ExecServicePrincipals { .FUNCTIONALITY Entrypoint,AnyTenant .ROLE - CIPP.Core.ReadWrite + Tenant.Application.ReadWrite #> [CmdletBinding()] param($Request, $TriggerMetadata) @@ -61,7 +61,12 @@ function Invoke-ExecServicePrincipals { $Results = New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/servicePrincipals/$($Request.Query.Id)" -tenantid $TenantFilter -NoAuthCheck $true } else { $Action = 'List' - $Results = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/servicePrincipals?$top=999&$orderby=displayName&$count=true' -ComplexFilter -tenantid $TenantFilter -NoAuthCheck $true + $Uri = 'https://graph.microsoft.com/beta/servicePrincipals?$top=999&$orderby=displayName&$count=true' + if ($Request.Query.Select) { + $Uri = '{0}&$select={1}' -f $Uri, $Request.Query.Select + } + + $Results = New-GraphGetRequest -Uri $Uri -ComplexFilter -tenantid $TenantFilter -NoAuthCheck $true } } } 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 index b9dd162b974e..10d66559b4b5 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ListScheduledItemDetails.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ListScheduledItemDetails.ps1 @@ -28,7 +28,7 @@ function Invoke-ListScheduledItemDetails { # 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 + $Task = Get-CIPPAzDataTableEntity @TaskTable -Filter "RowKey eq '$RowKey' and PartitionKey eq 'ScheduledTask'" | Select-Object RowKey, Name, TaskState, Command, Parameters, Recurrence, ExecutedTime, ScheduledTime, PostExecution, Tenant, TenantGroup, Hidden, Results, Timestamp if (-not $Task) { Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ @@ -57,6 +57,35 @@ function Invoke-ListScheduledItemDetails { $Task.ScheduledTime = [DateTimeOffset]::FromUnixTimeSeconds($Task.ScheduledTime).UtcDateTime } catch {} + # Handle tenant group display information (similar to Invoke-ListScheduledItems) + if ($Task.TenantGroup) { + try { + $TenantGroupObject = $Task.TenantGroup | ConvertFrom-Json -ErrorAction SilentlyContinue + if ($TenantGroupObject) { + # Create a tenant group object for the frontend formatting + $TenantGroupForDisplay = [PSCustomObject]@{ + label = $TenantGroupObject.label + value = $TenantGroupObject.value + type = 'Group' + } + $Task | Add-Member -NotePropertyName TenantGroupInfo -NotePropertyValue $TenantGroupForDisplay -Force + # Update the tenant to show the group object for proper formatting + $Task.Tenant = $TenantGroupForDisplay + } + } catch { + Write-Warning "Failed to parse tenant group information for task $($Task.RowKey): $($_.Exception.Message)" + # Fall back to keeping original tenant value + } + } else { + # For regular tenants, create a tenant object for consistent formatting + $TenantForDisplay = [PSCustomObject]@{ + label = $Task.Tenant + value = $Task.Tenant + type = 'Tenant' + } + $Task.Tenant = $TenantForDisplay + } + # Get the results if available $ResultsTable = Get-CIPPTable -TableName 'ScheduledTaskResults' $ResultsFilter = "PartitionKey eq '$RowKey'" diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ListScheduledItems.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ListScheduledItems.ps1 index 4361e6d64ee6..b60fe1e64a15 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ListScheduledItems.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Scheduler/Invoke-ListScheduledItems.ps1 @@ -75,13 +75,41 @@ function Invoke-ListScheduledItems { try { $Task.ScheduledTime = [DateTimeOffset]::FromUnixTimeSeconds($Task.ScheduledTime).UtcDateTime } catch {} + + # Handle tenant group display information + if ($Task.TenantGroup) { + try { + $TenantGroupObject = $Task.TenantGroup | ConvertFrom-Json -ErrorAction SilentlyContinue + if ($TenantGroupObject) { + # Create a tenant group object for the frontend formatting + $TenantGroupForDisplay = [PSCustomObject]@{ + label = $TenantGroupObject.label + value = $TenantGroupObject.value + type = 'Group' + } + $Task | Add-Member -NotePropertyName TenantGroupInfo -NotePropertyValue $TenantGroupForDisplay -Force + # Update the tenant to show the group object for proper formatting + $Task.Tenant = $TenantGroupForDisplay + } + } catch { + Write-Warning "Failed to parse tenant group information for task $($Task.RowKey): $($_.Exception.Message)" + # Fall back to keeping original tenant value + } + } else { + $Task.Tenant = [PSCustomObject]@{ + label = $Task.Tenant + value = $Task.Tenant + type = 'Tenant' + } + } + $Task } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK - Body = @($ScheduledTasks | Sort-Object -Property ExecutedTime -Descending) + Body = @($ScheduledTasks | Sort-Object -Property ScheduledTime, ExecutedTime -Descending) }) } 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 11a0a23f8716..c967d94f6f28 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 @@ -35,5 +35,4 @@ function Invoke-RemoveScheduledItem { Body = @{ Results = 'Task removed successfully.' } }) - } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExchangeRoleRepair.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExchangeRoleRepair.ps1 index 76cea5d8a031..4ce8b2264706 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExchangeRoleRepair.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecExchangeRoleRepair.ps1 @@ -15,7 +15,7 @@ function Invoke-ExecExchangeRoleRepair { try { Write-Information "Starting Exchange Organization Management role repair for tenant: $($Tenant.defaultDomainName)" - $OrgManagementRoles = New-ExoRequest -tenantid $Tenant.customerId -cmdlet 'Get-ManagementRoleAssignment' -cmdParams @{ RoleAssignee = 'Organization Management'; Delegating = $false } | Select-Object -Property Role, Guid + $OrgManagementRoles = New-ExoRequest -tenantid $Tenant.customerId -cmdlet 'Get-ManagementRoleAssignment' -cmdParams @{ Delegating = $false } | Where-Object { $_.RoleAssigneeName -eq 'Organization Management' } | Select-Object -Property Role, Guid Write-Information "Found $($OrgManagementRoles.Count) Organization Management roles in Exchange" $RoleDefinitions = New-GraphGetRequest -tenantid $Tenant.customerId -uri 'https://graph.microsoft.com/beta/roleManagement/exchange/roleDefinitions' @@ -53,7 +53,7 @@ function Invoke-ExecExchangeRoleRepair { state = 'success' resultText = "Successfully repaired the missing Organization Management roles: $($MissingOrgMgmtRoles.displayName -join ', ')" } - Write-LogMessage -headers $Headers -tenant $Tenant.defaultDomainName -tenantid $Tenant.customerId -Message "Successfully repaired the missing Organization Management roles: $($MissingOrgMgmtRoles.displayName -join ', '). Run another Tenant Access check after waiting a bit for replication." -sev 'Info' + Write-LogMessage -API 'ExecExchangeRoleRepair' -headers $Headers -tenant $Tenant.defaultDomainName -tenantid $Tenant.customerId -Message "Successfully repaired the missing Organization Management roles: $($MissingOrgMgmtRoles.displayName -join ', '). Run another Tenant Access check after waiting a bit for replication." -sev 'Info' } else { # Get roles that failed to repair $FailedRoles = $RepairResults | Where-Object { $_.status -ne 201 } | ForEach-Object { @@ -65,11 +65,13 @@ function Invoke-ExecExchangeRoleRepair { if ($RepairResults.status -in (401, 403, 500)) { $PermissionError = $true } + $LogData = $RepairResults | Select-Object -Property id, status, body $Results = @{ state = 'error' resultText = "Failed to repair the missing Organization Management roles: $($FailedRoles -join ', ').$(if ($PermissionError) { " This may be due to insufficient permissions. The required Graph Permission is 'Application - RoleManagement.ReadWrite.Exchange'" })" } - Write-LogMessage -headers $Headers -tenant $Tenant.defaultDomainName -tenantid $Tenant.customerId -Message "Failed to repair the missing Organization Management roles: $($FailedRoles -join ', ')" -sev 'Error' + Write-LogMessage -API 'ExecExchangeRoleRepair' -headers $Headers -tenant $Tenant.defaultDomainName -tenantid $Tenant.customerId -Message "Failed to repair the missing Organization Management roles: $($FailedRoles -join ', ')" -sev 'Error' -LogData $LogData + Write-Warning 'Exchange role repair failed' } } else { $Results = @{ @@ -80,7 +82,7 @@ function Invoke-ExecExchangeRoleRepair { } catch { $ErrorMessage = Get-CippException -Exception $_ Write-Warning "Exception during Exchange Organization Management role repair: $($ErrorMessage.NormalizedError)" - Write-LogMessage -headers $Headers -tenant $Tenant.defaultDomainName -tenantid $Tenant.customerId -Message "Exchange Organization Management role repair failed: $($ErrorMessage.NormalizedError)" -sev 'Error' -LogData $ErrorMessage + Write-LogMessage -API 'ExecExchangeRoleRepair' -headers $Headers -tenant $Tenant.defaultDomainName -tenantid $Tenant.customerId -Message "Exchange Organization Management role repair failed: $($ErrorMessage.NormalizedError)" -sev 'Error' -LogData $ErrorMessage $Results = @{ state = 'error' resultText = "Exchange Organization Management role repair failed: $($ErrorMessage.NormalizedError)" diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecPermissionRepair.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecPermissionRepair.ps1 index 499d31a60a22..c332ff12cd8b 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecPermissionRepair.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecPermissionRepair.ps1 @@ -26,6 +26,7 @@ function Invoke-ExecPermissionRepair { $NewPermissions = @{} foreach ($AppId in $AppIds) { + if (!$AppId) { continue } $ApplicationPermissions = [system.collections.generic.list[object]]::new() $DelegatedPermissions = [system.collections.generic.list[object]]::new() diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecTenantGroup.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecTenantGroup.ps1 index 029f21fe25be..5ab6cf634b28 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecTenantGroup.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecTenantGroup.ps1 @@ -7,7 +7,7 @@ function Invoke-ExecTenantGroup { .FUNCTIONALITY Entrypoint,AnyTenant .ROLE - TenantGroups.Config.ReadWrite + Tenant.Groups.ReadWrite #> [CmdletBinding()] param($Request, $TriggerMetadata) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ListCustomRole.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ListCustomRole.ps1 index a3c89065b371..51e23977d3ec 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ListCustomRole.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ListCustomRole.ps1 @@ -49,9 +49,31 @@ function Invoke-ListCustomRole { if ($Role.AllowedTenants) { try { $AllowedTenants = $Role.AllowedTenants | ConvertFrom-Json -ErrorAction Stop | ForEach-Object { - $TenantId = $_ - $TenantList | Where-Object { $_.customerId -eq $TenantId } | Select-Object -ExpandProperty defaultDomainName - } + if ($_ -is [PSCustomObject] -and $_.type -eq 'Group') { + # Return group objects as-is for frontend display + [PSCustomObject]@{ + type = 'Group' + value = $_.value + label = $_.label + } + } else { + # Convert tenant customer ID to domain name object for frontend + $TenantId = $_ + $TenantInfo = $TenantList | Where-Object { $_.customerId -eq $TenantId } + if ($TenantInfo) { + [PSCustomObject]@{ + type = 'Tenant' + value = $TenantInfo.defaultDomainName + label = "$($TenantInfo.displayName) ($($TenantInfo.defaultDomainName))" + addedFields = @{ + defaultDomainName = $TenantInfo.defaultDomainName + displayName = $TenantInfo.displayName + customerId = $TenantInfo.customerId + } + } + } + } + } | Where-Object { $_ -ne $null } $AllowedTenants = $AllowedTenants ?? @('AllTenants') $Role.AllowedTenants = @($AllowedTenants) } catch { @@ -63,9 +85,31 @@ function Invoke-ListCustomRole { if ($Role.BlockedTenants) { try { $BlockedTenants = $Role.BlockedTenants | ConvertFrom-Json -ErrorAction Stop | ForEach-Object { - $TenantId = $_ - $TenantList | Where-Object { $_.customerId -eq $TenantId } | Select-Object -ExpandProperty defaultDomainName - } + if ($_ -is [PSCustomObject] -and $_.type -eq 'Group') { + # Return group objects as-is for frontend display + [PSCustomObject]@{ + type = 'Group' + value = $_.value + label = $_.label + } + } else { + # Convert tenant customer ID to domain name object for frontend + $TenantId = $_ + $TenantInfo = $TenantList | Where-Object { $_.customerId -eq $TenantId } + if ($TenantInfo) { + [PSCustomObject]@{ + type = 'Tenant' + value = $TenantInfo.defaultDomainName + label = "$($TenantInfo.displayName) ($($TenantInfo.defaultDomainName))" + addedFields = @{ + defaultDomainName = $TenantInfo.defaultDomainName + displayName = $TenantInfo.displayName + customerId = $TenantInfo.customerId + } + } + } + } + } | Where-Object { $_ -ne $null } $BlockedTenants = $BlockedTenants ?? @() $Role.BlockedTenants = @($BlockedTenants) } catch { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-AddSharedMailbox.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-AddSharedMailbox.ps1 index 4ad094971c5d..be57d83d393f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-AddSharedMailbox.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-AddSharedMailbox.ps1 @@ -1,6 +1,6 @@ using namespace System.Net -Function Invoke-AddSharedMailbox { +function Invoke-AddSharedMailbox { <# .FUNCTIONALITY Entrypoint @@ -14,10 +14,10 @@ Function Invoke-AddSharedMailbox { $Headers = $Request.Headers Write-LogMessage -Headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' - $Results = [System.Collections.ArrayList]@() + $Results = [System.Collections.Generic.List[string]]::new() $MailboxObject = $Request.Body $Tenant = $MailboxObject.tenantID - $Aliases = $MailboxObject.addedAliases -Split '\n' + $Aliases = $MailboxObject.addedAliases -split '\n' try { @@ -29,18 +29,18 @@ Function Invoke-AddSharedMailbox { Shared = $true } $AddSharedRequest = New-ExoRequest -tenantid $Tenant -cmdlet 'New-Mailbox' -cmdParams $BodyToShip - $Body = $Results.Add("Successfully created shared mailbox: $Email") + $Results.Add("Successfully created shared mailbox: $Email.") Write-LogMessage -Headers $Headers -API $APIName -tenant $Tenant -message "Created shared mailbox $($MailboxObject.displayName) with email $Email" -Sev 'Info' # Block sign-in for the mailbox try { $null = Set-CIPPSignInState -userid $AddSharedRequest.ExternalDirectoryObjectId -TenantFilter $Tenant -APIName $APIName -Headers $Headers -AccountEnabled $false - $Body = $Results.Add("Blocked sign-in for shared mailbox $Email") + $Results.Add("Blocked sign-in for shared mailbox $Email") } catch { $ErrorMessage = Get-CippException -Exception $_ $Message = "Failed to block sign-in for shared mailbox $Email Error: $($ErrorMessage.NormalizedError)" Write-LogMessage -Headers $Headers -API $APIName -tenant $Tenant -message $Message -Sev 'Error' -LogData $ErrorMessage - $Body = $Results.Add($Message) + $Results.Add($Message) } # Add aliases to the mailbox if any are provided @@ -54,13 +54,13 @@ Function Invoke-AddSharedMailbox { $null = New-ExoRequest -tenantid $Tenant -cmdlet 'Set-Mailbox' -cmdParams $AliasBodyToShip -UseSystemMailbox $true $Message = "Added aliases to $Email : $($Aliases -join ',')" Write-LogMessage -Headers $Headers -API $APIName -tenant $Tenant -message $Message -Sev 'Info' - $Body = $Results.Add($Message) + $Results.Add($Message) } catch { $ErrorMessage = Get-CippException -Exception $_ $Message = "Failed to add aliases to $Email : $($ErrorMessage.NormalizedError)" Write-LogMessage -Headers $Headers -API $APIName -tenant $Tenant -message $Message -Sev 'Error' -LogData $ErrorMessage - $Body = $Results.Add($Message) + $Results.Add($Message) } } $StatusCode = [HttpStatusCode]::OK @@ -68,16 +68,15 @@ Function Invoke-AddSharedMailbox { $ErrorMessage = Get-CippException -Exception $_ $Message = "Failed to create shared mailbox. $($ErrorMessage.NormalizedError)" Write-LogMessage -Headers $Headers -API $APIName -tenant $Tenant -message $Message -Sev 'Error' -LogData $ErrorMessage - $Body = $Results.Add($Message) + $Results.Add($Message) $StatusCode = [HttpStatusCode]::Forbidden } - $Body = [pscustomobject] @{ Results = @($Results) } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = $StatusCode - Body = $Body + Body = @{ Results = @($Results) } }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecConvertMailbox.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecConvertMailbox.ps1 index b8bd40c0915a..40c35048cb4a 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecConvertMailbox.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecConvertMailbox.ps1 @@ -11,27 +11,25 @@ Function Invoke-ExecConvertMailbox { param($Request, $TriggerMetadata) $APIName = $Request.Params.CIPPEndpoint - $TenantFilter = $Request.Body.tenantFilter - 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 $UserID = $Request.Body.ID $MailboxType = $Request.Body.MailboxType try { - $ConvertedMailbox = Set-CIPPMailboxType -UserID $UserID -TenantFilter $TenantFilter -APIName $APIName -Headers $Request.Headers -MailboxType $MailboxType - if ($ConvertedMailbox -like 'Could not convert*') { throw $ConvertedMailbox } - $Results = [pscustomobject]@{'Results' = "$ConvertedMailbox" } + $Results = Set-CIPPMailboxType -UserID $UserID -TenantFilter $TenantFilter -APIName $APIName -Headers $Headers -MailboxType $MailboxType $StatusCode = [HttpStatusCode]::OK } catch { - $ErrorMessage = $_.Exception.Message - $Results = [pscustomobject]@{'Results' = "$ErrorMessage" } + $Results = $_.Exception.Message $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = $StatusCode - Body = $Results + Body = @{'Results' = $Results } }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEditMailboxPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEditMailboxPermissions.ps1 index 4743382dd6c9..c3fa53a4d50f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEditMailboxPermissions.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEditMailboxPermissions.ps1 @@ -11,7 +11,8 @@ Function Invoke-ExecEditMailboxPermissions { 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 = $request.body.userID $Tenantfilter = $request.body.tenantfilter if ($username -eq $null) { exit } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEmailForward.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEmailForward.ps1 index c9839dd12cf3..593c69f6eaac 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEmailForward.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecEmailForward.ps1 @@ -10,66 +10,61 @@ Function Invoke-ExecEmailForward { [CmdletBinding()] param($Request, $TriggerMetadata) - $Tenantfilter = $request.body.tenantfilter - $username = $request.body.userid - if ($request.body.ForwardInternal -is [string]) { - $ForwardingAddress = $request.body.ForwardInternal - } else {($request.body.ForwardInternal.value) - $ForwardingAddress = $request.body.ForwardInternal.value - } - $ForwardingSMTPAddress = $request.body.ForwardExternal - $ForwardOption = $request.body.forwardOption + $APIName = $Request.Params.CIPPEndpoint - [bool]$KeepCopy = if ($request.body.KeepCopy -eq 'true') { $true } else { $false } + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APINAME-message 'Accessed this API' -Sev 'Debug' - if ($ForwardOption -eq 'internalAddress') { - try { - Set-CIPPForwarding -userid $username -tenantFilter $TenantFilter -APIName $APINAME -Headers $Request.Headers -Forward $ForwardingAddress -KeepCopy $KeepCopy - if (-not $request.body.KeepCopy) { - $results = "Forwarding all email for $($username) to $($ForwardingAddress) and not keeping a copy" - } else { - $results = "Forwarding all email for $($username) to $($ForwardingAddress) and keeping a copy" - } - } catch { - Write-LogMessage -headers $Request.Headers -API $APINAME -message "Could not add forwarding for $($username)" -Sev 'Error' -tenant $TenantFilter - $results = "Could not add forwarding for $($username). Error: $($_.Exception.Message)" - } + $TenantFilter = $Request.Body.tenantFilter + $Username = $Request.Body.userID + if ($Request.Body.ForwardInternal -is [string]) { + $ForwardingAddress = $Request.Body.ForwardInternal + } else { + $ForwardingAddress = $Request.Body.ForwardInternal.value } + $ForwardingSMTPAddress = $Request.Body.ForwardExternal + $ForwardOption = $Request.Body.forwardOption + [bool]$KeepCopy = if ($Request.Body.KeepCopy -eq 'true') { $true } else { $false } - if ($ForwardOption -eq 'ExternalAddress') { - try { - Set-CIPPForwarding -userid $username -tenantFilter $TenantFilter -APIName $APINAME -Headers $Request.Headers -forwardingSMTPAddress $ForwardingSMTPAddress -KeepCopy $KeepCopy - if (-not $request.body.KeepCopy) { - $results = "Forwarding all email for $($username) to $($ForwardingSMTPAddress) and not keeping a copy" - } else { - $results = "Forwarding all email for $($username) to $($ForwardingSMTPAddress) and keeping a copy" + # Process the forwarding option based on the type selected + switch ($ForwardOption) { + 'internalAddress' { + # Set up internal forwarding to another mailbox within the organization + try { + $Results = Set-CIPPForwarding -UserID $Username -TenantFilter $TenantFilter -APIName $APIName -Headers $Headers -Forward $ForwardingAddress -KeepCopy $KeepCopy + $StatusCode = [HttpStatusCode]::OK + } catch { + $Results = $_.Exception.Message + $StatusCode = [HttpStatusCode]::InternalServerError } - } catch { - Write-LogMessage -headers $Request.Headers -API $APINAME -message "Could not add forwarding for $($username)" -Sev 'Error' -tenant $TenantFilter - $results = "Could not add forwarding for $($username). Error: $($_.Exception.Message)" - } - - } - - if ($ForwardOption -eq 'disabled') { - try { - Set-CIPPForwarding -userid $username -username $username -tenantFilter $Tenantfilter -Headers $Request.Headers -APIName $APIName -Disable $true - $results = "Disabled Email Forwarding for $($username)" - } catch { - Write-LogMessage -headers $Request.Headers -API $APINAME -message "Could not disable Email forwarding for $($username)" -Sev 'Error' -tenant $TenantFilter - $results = "Could not disable Email forwarding for $($username). Error: $($_.Exception.Message)" - + 'ExternalAddress' { + # Set up external forwarding to an SMTP address outside the organization + try { + $Results = Set-CIPPForwarding -UserID $Username -TenantFilter $TenantFilter -APIName $APIName -Headers $Headers -ForwardingSMTPAddress $ForwardingSMTPAddress -KeepCopy $KeepCopy + $StatusCode = [HttpStatusCode]::OK + } catch { + $Results = $_.Exception.Message + $StatusCode = [HttpStatusCode]::InternalServerError + } + } + 'disabled' { + # Disable email forwarding for the specified user + try { + $Results = Set-CIPPForwarding -UserID $Username -Username $Username -TenantFilter $TenantFilter -Headers $Headers -APIName $APIName -Disable $true + $StatusCode = [HttpStatusCode]::OK + } catch { + $Results = $_.Exception.Message + $StatusCode = [HttpStatusCode]::InternalServerError + } } } - $Body = @{'Results' = @($results) } - # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ - StatusCode = [HttpStatusCode]::OK - Body = $Body + StatusCode = $StatusCode + Body = @{'Results' = @($Results) } }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecRemoveMailboxRule.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecRemoveMailboxRule.ps1 index 4693975d05a9..ec262837d003 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecRemoveMailboxRule.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Administration/Invoke-ExecRemoveMailboxRule.ps1 @@ -20,19 +20,19 @@ Function Invoke-ExecRemoveMailboxRule { $RuleId = $Request.Query.ruleId ?? $Request.Body.ruleId $Username = $Request.Query.userPrincipalName ?? $Request.Body.userPrincipalName - # Remove the rule - $Results = Remove-CIPPMailboxRule -username $Username -TenantFilter $TenantFilter -APIName $APIName -Headers $Headers -RuleId $RuleId -RuleName $RuleName - - if ($Results -like '*Could not delete*') { - $StatusCode = [HttpStatusCode]::InternalServerError - } else { + try { + # Remove the rule + $Results = Remove-CIPPMailboxRule -username $Username -TenantFilter $TenantFilter -APIName $APIName -Headers $Headers -RuleId $RuleId -RuleName $RuleName $StatusCode = [HttpStatusCode]::OK + } catch { + $Results = $_.Exception.Message + $StatusCode = [HttpStatusCode]::InternalServerError } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = $StatusCode - Body = @{ Results = $Results } + Body = @{ 'Results' = $Results } }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-AddEquipmentMailbox.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-AddEquipmentMailbox.ps1 index 93497681a93a..1bff3ee58b80 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-AddEquipmentMailbox.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-AddEquipmentMailbox.ps1 @@ -34,12 +34,11 @@ Function Invoke-AddEquipmentMailbox { # Block sign-in for the mailbox try { - $BlockSignInRequest = Set-CIPPSignInState -userid $AddEquipmentRequest.ExternalDirectoryObjectId -TenantFilter $Tenant -APIName $APINAME -Headers $Headers -AccountEnabled $false - if ($BlockSignInRequest -like 'Could not disable*') { throw $BlockSignInRequest } - $Results.Add("Blocked sign-in for Equipment mailbox; $($MailboxObject.userPrincipalName)") + $null = Set-CIPPSignInState -userid $AddEquipmentRequest.ExternalDirectoryObjectId -TenantFilter $Tenant -APIName $APINAME -Headers $Headers -AccountEnabled $false + $Results.Add("Successfully blocked sign-in for Equipment mailbox $($MailboxObject.userPrincipalName)") } catch { - $ErrorMessage = Get-CippException -Exception $_ - $Results.Add("Failed to block sign-in for Equipment mailbox: $($MailboxObject.userPrincipalName). Error: $($ErrorMessage.NormalizedError)") + $ErrorMessage = $_.Exception.Message + $Results.Add("Failed to block sign-in for Equipment mailbox: $($MailboxObject.userPrincipalName). Error: $ErrorMessage") } Write-LogMessage -headers $Headers -API $APIName -tenant $Tenant -message "Created equipment mailbox $($MailboxObject.displayName)" -Sev 'Info' $StatusCode = [HttpStatusCode]::OK diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-AddRoomList.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-AddRoomList.ps1 new file mode 100644 index 000000000000..71135e9f31bb --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-AddRoomList.ps1 @@ -0,0 +1,57 @@ +using namespace System.Net + +Function Invoke-AddRoomList { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.Room.ReadWrite + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + $Tenant = $Request.Body.tenantFilter ?? $Request.Body.tenantid + + $Results = [System.Collections.Generic.List[Object]]::new() + $RoomListObject = $Request.Body + + # Construct email address from username and domain + $EmailAddress = if ($RoomListObject.primDomain.value) { + "$($RoomListObject.username)@$($RoomListObject.primDomain.value)" + } else { + "$($RoomListObject.username)@$($Tenant)" + } + + # Parameters for New-DistributionGroup with RoomList + $AddRoomListParams = @{ + Name = $RoomListObject.username + DisplayName = $RoomListObject.displayName + RoomList = $true + PrimarySMTPAddress = $EmailAddress + } + + try { + $AddRoomListRequest = New-ExoRequest -tenantid $Tenant -cmdlet 'New-DistributionGroup' -cmdParams $AddRoomListParams + $Results.Add("Successfully created room list: $($RoomListObject.displayName).") + Write-LogMessage -Headers $Headers -API $APINAME -tenant $Tenant -message "Created room list $($RoomListObject.displayName) with id $($AddRoomListRequest.identity)" -Sev 'Info' + + $StatusCode = [HttpStatusCode]::OK + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Message = "Failed to create room list: $($RoomListObject.displayName). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -Headers $Headers -API $APIName -tenant $Tenant -message $Message -Sev 'Error' -LogData $ErrorMessage + $Results.Add($Message) + $StatusCode = [HttpStatusCode]::InternalServerError + } + + $Body = [pscustomobject] @{ 'Results' = @($Results) } + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = $Body + }) +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-AddRoomMailbox.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-AddRoomMailbox.ps1 index d174b644ab39..50888f859309 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-AddRoomMailbox.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-AddRoomMailbox.ps1 @@ -32,12 +32,11 @@ Function Invoke-AddRoomMailbox { # Block sign-in for the mailbox try { - $BlockSignInRequest = Set-CIPPSignInState -userid $AddRoomRequest.ExternalDirectoryObjectId -TenantFilter $Tenant -APIName $APINAME -Headers $Headers -AccountEnabled $false - if ($BlockSignInRequest -like 'Could not disable*') { throw $BlockSignInRequest } - $Results.Add("Blocked sign-in for Room mailbox; $($MailboxObject.userPrincipalName)") + $null = Set-CIPPSignInState -userid $AddRoomRequest.ExternalDirectoryObjectId -TenantFilter $Tenant -APIName $APINAME -Headers $Headers -AccountEnabled $false + $Results.Add("Successfully blocked sign-in for Room mailbox $($MailboxObject.userPrincipalName)") } catch { - $ErrorMessage = Get-CippException -Exception $_ - $Results.Add("Failed to block sign-in for Room mailbox: $($MailboxObject.userPrincipalName). Error: $($ErrorMessage.NormalizedError)") + $ErrorMessage = $_.Exception.Message + $Results.Add("Failed to block sign-in for Room mailbox: $($MailboxObject.userPrincipalName). Error: $ErrorMessage") } $StatusCode = [HttpStatusCode]::OK } catch { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-EditRoomList.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-EditRoomList.ps1 new file mode 100644 index 000000000000..dfe1a1393259 --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Resources/Invoke-EditRoomList.ps1 @@ -0,0 +1,177 @@ +using namespace System.Net + +Function Invoke-EditRoomList { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Exchange.Room.ReadWrite + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + $Results = [System.Collections.Generic.List[string]]::new() + $RoomListObj = $Request.Body + $GroupId = $RoomListObj.groupId + $TenantId = $RoomListObj.tenantFilter + + try { + # Edit basic room list properties + if ($RoomListObj.displayName -or $RoomListObj.description -or $RoomListObj.mailNickname) { + $SetRoomListParams = @{ + Identity = $GroupId + } + + if ($RoomListObj.displayName) { + $SetRoomListParams.DisplayName = $RoomListObj.displayName + } + + if ($RoomListObj.description) { + $SetRoomListParams.Description = $RoomListObj.description + } + + if ($RoomListObj.mailNickname) { + $SetRoomListParams.Name = $RoomListObj.mailNickname + } + + try { + $null = New-ExoRequest -tenantid $TenantId -cmdlet 'Set-DistributionGroup' -cmdParams $SetRoomListParams -useSystemMailbox $true + $Results.Add("Successfully updated room list properties for $($RoomListObj.displayName)") + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Updated room list properties for $($RoomListObj.displayName)" -Sev 'Info' + } catch { + $Results.Add("Failed to update room list properties: $($_.Exception.Message)") + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Failed to update room list properties: $($_.Exception.Message)" -Sev 'Error' + } + } + + # Add room members + if ($RoomListObj.AddMember) { + foreach ($Member in $RoomListObj.AddMember) { + try { + $MemberEmail = if ($Member.value) { $Member.value } else { $Member } + $AddMemberParams = @{ + Identity = $GroupId + Member = $MemberEmail + BypassSecurityGroupManagerCheck = $true + } + + $null = New-ExoRequest -tenantid $TenantId -cmdlet 'Add-DistributionGroupMember' -cmdParams $AddMemberParams -useSystemMailbox $true + $Results.Add("Successfully added room $MemberEmail to room list") + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Added room $MemberEmail to room list $GroupId" -Sev 'Info' + } catch { + $Results.Add("Failed to add room $MemberEmail : $($_.Exception.Message)") + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Failed to add room $MemberEmail : $($_.Exception.Message)" -Sev 'Error' + } + } + } + + # Remove room members + if ($RoomListObj.RemoveMember) { + foreach ($Member in $RoomListObj.RemoveMember) { + try { + $MemberEmail = if ($Member.value) { $Member.value } else { $Member } + $RemoveMemberParams = @{ + Identity = $GroupId + Member = $MemberEmail + BypassSecurityGroupManagerCheck = $true + } + + $null = New-ExoRequest -tenantid $TenantId -cmdlet 'Remove-DistributionGroupMember' -cmdParams $RemoveMemberParams -useSystemMailbox $true + $Results.Add("Successfully removed room $MemberEmail from room list") + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Removed room $MemberEmail from room list $GroupId" -Sev 'Info' + } catch { + $Results.Add("Failed to remove room $MemberEmail from room list: $($_.Exception.Message)") + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Failed to remove room $MemberEmail from room list: $($_.Exception.Message)" -Sev 'Error' + } + } + } + + # Handle owners (ManagedBy property) + if ($RoomListObj.AddOwner -or $RoomListObj.RemoveOwner) { + try { + # Get current owners + $CurrentGroup = New-ExoRequest -tenantid $TenantId -cmdlet 'Get-DistributionGroup' -cmdParams @{ Identity = $GroupId } -useSystemMailbox $true + $CurrentOwners = [System.Collections.Generic.List[string]]::new() + + if ($CurrentGroup.ManagedBy) { + # Convert ManagedBy objects to strings explicitly + foreach ($ManagedByItem in $CurrentGroup.ManagedBy) { + $StringValue = [string]$ManagedByItem + $CurrentOwners.Add($StringValue) + } + } + + # Remove owners + if ($RoomListObj.RemoveOwner) { + foreach ($Owner in $RoomListObj.RemoveOwner) { + $OwnerToRemove = if ($Owner.addedFields.id) { $Owner.addedFields.id } else { $Owner.value } + if ($CurrentOwners -contains $OwnerToRemove) { + $CurrentOwners.Remove($OwnerToRemove) + $Results.Add("Removed owner $(if ($Owner.label) { $Owner.label } else { $OwnerToRemove }) from room list") + } + } + } + + # Add owners + if ($RoomListObj.AddOwner) { + foreach ($Owner in $RoomListObj.AddOwner) { + $OwnerToAdd = if ($Owner.addedFields.id) { $Owner.addedFields.id } else { $Owner.value } + if ($CurrentOwners -notcontains $OwnerToAdd) { + $CurrentOwners.Add($OwnerToAdd) + $Results.Add("Added owner $(if ($Owner.label) { $Owner.label } else { $OwnerToAdd }) to room list") + } + } + } + + # Update ManagedBy with new owners list + $SetOwnersParams = @{ + Identity = $GroupId + ManagedBy = $CurrentOwners.ToArray() + } + + $null = New-ExoRequest -tenantid $TenantId -cmdlet 'Set-DistributionGroup' -cmdParams $SetOwnersParams -useSystemMailbox $true + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Updated owners for room list $GroupId" -Sev 'Info' + } catch { + $Results.Add("Failed to update room list owners: $($_.Exception.Message)") + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Failed to update room list owners: $($_.Exception.Message)" -Sev 'Error' + } + } + + # Handle external email settings + if ($null -ne $RoomListObj.allowExternal) { + try { + $SetExternalParams = @{ + Identity = $GroupId + RequireSenderAuthenticationEnabled = !$RoomListObj.allowExternal + } + + $null = New-ExoRequest -tenantid $TenantId -cmdlet 'Set-DistributionGroup' -cmdParams $SetExternalParams -useSystemMailbox $true + + if ($RoomListObj.allowExternal) { + $Results.Add('Enabled external email access for room list') + } else { + $Results.Add('Disabled external email access for room list') + } + + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Updated external email settings for room list $GroupId" -Sev 'Info' + } catch { + $Results.Add("Failed to update external email settings: $($_.Exception.Message)") + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Failed to update external email settings: $($_.Exception.Message)" -Sev 'Error' + } + } + + } catch { + $Results.Add("An error occurred while editing the room list: $($_.Exception.Message)") + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Failed to edit room list: $($_.Exception.Message)" -Sev 'Error' + } + + # Associate values to output bindings by calling 'Push-OutputBinding'. + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = @{'Results' = @($Results) } + }) +} 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 be10ef655ae7..fc17e325ad3f 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 @@ -16,25 +16,102 @@ Function Invoke-ListRoomLists { # Interact with query parameters or the body of the request. $TenantFilter = $Request.Query.tenantFilter + $GroupID = $Request.Query.groupID + $Members = $Request.Query.members + $Owners = $Request.Query.owners try { - $params = @{ - uri = 'https://graph.microsoft.com/beta/places/microsoft.graph.roomlist' - tenantid = $TenantFilter - AsApp = $true - } - $GraphRequest = New-GraphGetRequest @params + if ($GroupID) { + # Get specific room list with detailed information + $GroupInfo = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-DistributionGroup' -cmdParams @{Identity = $GroupID } -useSystemMailbox $true | + Select-Object -ExcludeProperty *data.type* + + $Result = [PSCustomObject]@{ + groupInfo = $GroupInfo | Select-Object *, @{ Name = 'primDomain'; Expression = { $_.PrimarySmtpAddress -split '@' | Select-Object -Last 1 } } + members = @{} + owners = @{} + allowExternal = (!$GroupInfo.RequireSenderAuthenticationEnabled) + } + + # Get members if requested + if ($Members -eq 'true') { + $RoomListMembers = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-DistributionGroupMember' -cmdParams @{Identity = $GroupID } | Select-Object -ExcludeProperty *data.type* -Property @{Name = 'id'; Expression = { $_.ExternalDirectoryObjectId } }, + @{Name = 'displayName'; Expression = { $_.DisplayName } }, + @{Name = 'mail'; Expression = { $_.PrimarySmtpAddress } }, + @{Name = 'mailNickname'; Expression = { $_.Alias } }, + @{Name = 'userPrincipalName'; Expression = { $_.PrimarySmtpAddress } } + $Result.members = @($RoomListMembers) + } + + # Get owners if requested + if ($Owners -eq 'true' -and $GroupInfo.ManagedBy) { + try { + # Separate valid and invalid GUIDs + $ValidOwnerIds = [System.Collections.Generic.List[string]]::new() + $InvalidOwnerIds = [System.Collections.Generic.List[string]]::new() + + foreach ($OwnerId in $GroupInfo.ManagedBy) { + $OwnerIdString = [string]$OwnerId + # Check if it's a valid GUID format + if ($OwnerIdString -match '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$') { + $ValidOwnerIds.Add($OwnerIdString) + } else { + $InvalidOwnerIds.Add($OwnerIdString) + Write-Warning "Found invalid GUID for owner: $OwnerIdString" + } + } + + $AllOwners = [System.Collections.Generic.List[PSCustomObject]]::new() + + # Get valid owners from Graph API + if ($ValidOwnerIds.Count -gt 0) { + $body = ConvertTo-Json -InputObject @{ids = @($ValidOwnerIds) } -Compress + $OwnersData = New-GraphPOSTRequest -tenantid $TenantFilter -uri 'https://graph.microsoft.com/beta/directoryObjects/getByIds' -body $body + foreach ($Owner in $OwnersData.value) { + $AllOwners.Add($Owner) + } + } - $StatusCode = [HttpStatusCode]::OK + # Add invalid GUIDs as placeholder objects so they can be removed + foreach ($InvalidId in $InvalidOwnerIds) { + $PlaceholderOwner = [PSCustomObject]@{ + id = $InvalidId + displayName = "Invalid Owner ID: $InvalidId" + userPrincipalName = "invalid-$InvalidId" + '@odata.type' = '#microsoft.graph.user' + } + $AllOwners.Add($PlaceholderOwner) + } + + $Result.owners = @($AllOwners) + + } catch { + Write-Warning "Failed to get owners: $($_.Exception.Message)" + $Result.owners = @() + } + } + + + + $StatusCode = [HttpStatusCode]::OK + $ResponseBody = $Result + } else { + # Get all room lists (original functionality) + $RoomLists = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-DistributionGroup' -cmdParams @{RecipientTypeDetails = 'RoomList'; ResultSize = 'Unlimited' } | + Select-Object Guid, DisplayName, PrimarySmtpAddress, Alias, Phone, Identity, Notes, Description, Id -ExcludeProperty *data.type* + $StatusCode = [HttpStatusCode]::OK + $ResponseBody = @{ Results = @($RoomLists | Sort-Object DisplayName) } + } } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - $StatusCode = [HttpStatusCode]::Forbidden - $GraphRequest = $ErrorMessage + $StatusCode = [HttpStatusCode]::InternalServerError + $ResponseBody = $ErrorMessage } + # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = $StatusCode - Body = @($GraphRequest | Sort-Object displayName) + Body = $ResponseBody }) } 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 f7e20a67660a..5ccce144b576 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 @@ -18,45 +18,48 @@ Function Invoke-AddDefenderDeployment { if ('AllTenants' -in $Tenants) { $Tenants = (Get-Tenants -IncludeErrors).defaultDomainName } $Compliance = $Request.Body.Compliance $PolicySettings = $Request.Body.Policy + $DefenderExclusions = $Request.Body.Exclusion $ASR = $Request.Body.ASR $EDR = $Request.Body.EDR - $results = foreach ($tenant in $Tenants) { + $Results = foreach ($tenant in $Tenants) { try { - $SettingsObject = @{ - id = 'fc780465-2017-40d4-a0c5-307022471b92' - androidEnabled = [bool]$Compliance.ConnectAndroid - iosEnabled = [bool]$Compliance.ConnectIos - windowsEnabled = [bool]$Compliance.Connectwindows - macEnabled = [bool]$Compliance.ConnectMac - partnerUnsupportedOsVersionBlocked = [bool]$Compliance.BlockunsupportedOS - partnerUnresponsivenessThresholdInDays = 7 - allowPartnerToCollectIOSApplicationMetadata = [bool]$Compliance.ConnectIosCompliance - allowPartnerToCollectIOSPersonalApplicationMetadata = [bool]$Compliance.ConnectIosCompliance - androidMobileApplicationManagementEnabled = [bool]$Compliance.ConnectAndroidCompliance - iosMobileApplicationManagementEnabled = [bool]$Compliance.appSync - microsoftDefenderForEndpointAttachEnabled = [bool]$true - } - $SettingsObj = $SettingsObject | ConvertTo-Json -Compress - try { - $ExistingSettings = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/mobileThreatDefenseConnectors/fc780465-2017-40d4-a0c5-307022471b92' -tenantid $tenant + if ($Compliance) { + $SettingsObject = @{ + id = 'fc780465-2017-40d4-a0c5-307022471b92' + androidEnabled = [bool]$Compliance.ConnectAndroid + iosEnabled = [bool]$Compliance.ConnectIos + windowsEnabled = [bool]$Compliance.Connectwindows + macEnabled = [bool]$Compliance.ConnectMac + partnerUnsupportedOsVersionBlocked = [bool]$Compliance.BlockunsupportedOS + partnerUnresponsivenessThresholdInDays = 7 + allowPartnerToCollectIOSApplicationMetadata = [bool]$Compliance.ConnectIosCompliance + allowPartnerToCollectIOSPersonalApplicationMetadata = [bool]$Compliance.ConnectIosCompliance + androidMobileApplicationManagementEnabled = [bool]$Compliance.ConnectAndroidCompliance + iosMobileApplicationManagementEnabled = [bool]$Compliance.appSync + microsoftDefenderForEndpointAttachEnabled = [bool]$true + } + $SettingsObj = $SettingsObject | ConvertTo-Json -Compress + try { + $ExistingSettings = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/mobileThreatDefenseConnectors/fc780465-2017-40d4-a0c5-307022471b92' -tenantid $tenant - # Check if any setting doesn't match - foreach ($key in $SettingsObject.Keys) { - if ($ExistingSettings.$key -ne $SettingsObject[$key]) { - $ExistingSettings = $false - break + # Check if any setting doesn't match + foreach ($key in $SettingsObject.Keys) { + if ($ExistingSettings.$key -ne $SettingsObject[$key]) { + $ExistingSettings = $false + break + } } + } catch { + $ExistingSettings = $false + } + if ($ExistingSettings) { + "Defender Intune Configuration already correct and active for $($tenant). Skipping" + } else { + $null = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/mobileThreatDefenseConnectors/' -tenantid $tenant -type POST -body $SettingsObj -AsApp $true + "$($tenant): Successfully set Defender Compliance and Reporting settings. Please remember to enable the Intune Connector in the Defender portal." } - } catch { - $ExistingSettings = $false } - if ($ExistingSettings) { - "Defender Intune Configuration already correct and active for $($tenant). Skipping" - } else { - $null = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/mobileThreatDefenseConnectors/' -tenantid $tenant -type POST -body $SettingsObj -AsApp $true - "$($tenant): Successfully set Defender Compliance and Reporting settings. Please remember to enable the Intune Connector in the Defender portal." - } if ($PolicySettings) { $Settings = switch ($PolicySettings) { @@ -117,7 +120,7 @@ Function Invoke-AddDefenderDeployment { if ($PolicySettings.AssignTo -ne 'None') { $AssignBody = if ($PolicySettings.AssignTo -ne 'AllDevicesAndUsers') { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.' + $($PolicySettings.AssignTo) + 'AssignmentTarget"}}]}' } else { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}},{"id":"","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"}}]}' } $null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($PolicyRequest.id)')/assign" -tenantid $tenant -type POST -body $AssignBody - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($tenant) -message "Assigned policy $($DisplayName) to $($PolicySettings.AssignTo)" -Sev 'Info' + Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenant) -message "Assigned policy $($DisplayName) to $($PolicySettings.AssignTo)" -Sev 'Info' } "$($tenant): Successfully set Default AV Policy settings" } @@ -175,7 +178,7 @@ Function Invoke-AddDefenderDeployment { if ($ASR.AssignTo -and $ASR.AssignTo -ne 'none') { $AssignBody = if ($ASR.AssignTo -ne 'AllDevicesAndUsers') { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.' + $($asr.AssignTo) + 'AssignmentTarget"}}]}' } else { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}},{"id":"","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"}}]}' } $null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($ASRRequest.id)')/assign" -tenantid $tenant -type POST -body $AssignBody - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($tenant) -message "Assigned policy $($DisplayName) to $($ASR.AssignTo)" -Sev 'Info' + Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenant) -message "Assigned policy $($DisplayName) to $($ASR.AssignTo)" -Sev 'Info' } "$($tenant): Successfully added ASR Settings" } @@ -252,26 +255,105 @@ Function Invoke-AddDefenderDeployment { if ($ASR -and $ASR.AssignTo -ne 'none') { $AssignBody = if ($ASR.AssignTo -ne 'AllDevicesAndUsers') { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.' + $($asr.AssignTo) + 'AssignmentTarget"}}]}' } else { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}},{"id":"","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"}}]}' } $null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($EDRRequest.id)')/assign" -tenantid $tenant -type POST -body $AssignBody - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($tenant) -message "Assigned EDR policy $($DisplayName) to $($ASR.AssignTo)" -Sev 'Info' + Write-LogMessage -headers $Headers -API $APINAME -tenant $($tenant) -message "Assigned EDR policy $($DisplayName) to $($ASR.AssignTo)" -Sev 'Info' } "$($tenant): Successfully added EDR Settings" } } } + # Exclusion Policy Section + if ($DefenderExclusions) { + $ExclusionAssignTo = $DefenderExclusions.AssignTo + if ($DefenderExclusions.excludedExtensions) { + $ExcludedExtensions = $DefenderExclusions.excludedExtensions | Where-Object { $_ -and $_.Trim() } | ForEach-Object { + @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationStringSettingValue'; value = $_ } + } + } + if ($DefenderExclusions.excludedPaths) { + $ExcludedPaths = $DefenderExclusions.excludedPaths | Where-Object { $_ -and $_.Trim() } | ForEach-Object { + @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationStringSettingValue'; value = $_ } + } + } + if ($DefenderExclusions.excludedProcesses) { + $ExcludedProcesses = $DefenderExclusions.excludedProcesses | Where-Object { $_ -and $_.Trim() } | ForEach-Object { + @{ '@odata.type' = '#microsoft.graph.deviceManagementConfigurationStringSettingValue'; value = $_ } + } + } + $ExclusionSettings = [System.Collections.Generic.List[System.Object]]::new() + if ($ExcludedExtensions.Count -gt 0) { + $ExclusionSettings.Add(@{ + id = '2' + settingInstance = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance' + settingDefinitionId = 'device_vendor_msft_policy_config_defender_excludedextensions' + settingInstanceTemplateReference = @{ settingInstanceTemplateId = 'c203725b-17dc-427b-9470-673a2ce9cd5e' } + simpleSettingCollectionValue = @($ExcludedExtensions) + } + }) + } + if ($ExcludedPaths.Count -gt 0) { + $ExclusionSettings.Add(@{ + id = '1' + settingInstance = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance' + settingDefinitionId = 'device_vendor_msft_policy_config_defender_excludedpaths' + settingInstanceTemplateReference = @{ settingInstanceTemplateId = 'aaf04adc-c639-464f-b4a7-152e784092e8' } + simpleSettingCollectionValue = @($ExcludedPaths) + } + }) + } + if ($ExcludedProcesses.Count -gt 0) { + $ExclusionSettings.Add(@{ + id = '0' + settingInstance = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance' + settingDefinitionId = 'device_vendor_msft_policy_config_defender_excludedprocesses' + settingInstanceTemplateReference = @{ settingInstanceTemplateId = '96b046ed-f138-4250-9ae0-b0772a93d16f' } + simpleSettingCollectionValue = @($ExcludedProcesses) + } + }) + } + if ($ExclusionSettings.Count -gt 0) { + $ExclusionBody = ConvertTo-Json -Depth 15 -Compress -InputObject @{ + name = 'Default AV Exclusion Policy' + displayName = 'Default AV Exclusion Policy' + settings = @($ExclusionSettings) + platforms = 'windows10' + technologies = 'mdm,microsoftSense' + templateReference = @{ + templateId = '45fea5e9-280d-4da1-9792-fb5736da0ca9_1' + templateFamily = 'endpointSecurityAntivirus' + templateDisplayName = 'Microsoft Defender Antivirus exclusions' + templateDisplayVersion = 'Version 1' + } + } + $CheckExistingExclusion = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies' -tenantid $tenant + if ('Default AV Exclusion Policy' -in $CheckExistingExclusion.Name) { + "$($tenant): Exclusion Policy already exists. Skipping" + } else { + $ExclusionRequest = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies' -tenantid $tenant -type POST -body $ExclusionBody + if ($ExclusionAssignTo -and $ExclusionAssignTo -ne 'none') { + $AssignBody = if ($ExclusionAssignTo -ne 'AllDevicesAndUsers') { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.' + $($ExclusionAssignTo) + 'AssignmentTarget"}}]}' } else { '{"assignments":[{"id":"","target":{"@odata.type":"#microsoft.graph.allDevicesAssignmentTarget"}},{"id":"","target":{"@odata.type":"#microsoft.graph.allLicensedUsersAssignmentTarget"}}]}' } + $null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies('$($ExclusionRequest.id)')/assign" -tenantid $tenant -type POST -body $AssignBody + Write-LogMessage -headers $Headers -API $APIName -tenant $tenant -message "Assigned Exclusion policy to $($ExclusionAssignTo)" -Sev 'Info' + } + "$($tenant): Successfully set Default AV Exclusion Policy settings" + } + } + } } catch { "Failed to add policy for $($tenant): $($_.Exception.Message)" - Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($tenant) -message "Failed adding policy $($DisplayName). Error: $($_.Exception.Message)" -Sev 'Error' + Write-LogMessage -headers $Headers -API $APIName -tenant $tenant -message "Failed adding policy $($DisplayName). Error: $($_.Exception.Message)" -Sev 'Error' continue } } - $body = [pscustomobject]@{'Results' = @($results) } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK - Body = $body + Body = @{'Results' = @($Results) } }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-EditIntuneScript.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Endpoint/MEM/Invoke-EditIntuneScript.ps1 index 715bdd7b3c52..c084cd79206a 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 @@ -72,6 +72,12 @@ function Invoke-EditIntuneScript { } } 'PATCH' { + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::BadRequest + Body = "Method $($Request.Method) is not supported." + }) + } + 'POST' { # Parse the script data to determine type $scriptData = $Request.Body.IntuneScript | ConvertFrom-Json $scriptType = $Request.Body.ScriptType @@ -116,8 +122,5 @@ function Invoke-EditIntuneScript { }) } } - 'POST' { - Write-Output 'Adding script' - } } } 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 34ec25c7abdc..18cd79effab4 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 @@ -15,13 +15,13 @@ function Invoke-EditGroup { $Results = [System.Collections.Generic.List[string]]@() $UserObj = $Request.Body $GroupType = $UserObj.groupId.addedFields.groupType ? $UserObj.groupId.addedFields.groupType : $UserObj.groupType - $GroupName = $UserObj.groupName ? $UserObj.groupName : $UserObj.groupId.addedFields.groupName + # groupName is used in the Add to Group user action, displayName is used in the Edit Group page + $GroupName = $UserObj.groupName ?? $UserObj.displayName ?? $UserObj.groupId.addedFields.groupName $GroupId = $UserObj.groupId.value ?? $UserObj.groupId $OrgGroup = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/groups/$($GroupId)" -tenantid $UserObj.tenantFilter $AddMembers = $UserObj.AddMember - $TenantId = $UserObj.tenantId ?? $UserObj.tenantFilter $MemberODataBindString = 'https://graph.microsoft.com/v1.0/directoryObjects/{0}' @@ -69,8 +69,8 @@ function Invoke-EditGroup { $AddMembers | ForEach-Object { try { # Add to group user action and edit group page sends in different formats, so we need to handle both - $Member = $_.value ?? $_ - $MemberID = $_.addedFields.id + $Member = $_.addedFields.userPrincipalName ?? $_.value ?? $_ + $MemberID = $_.value if (!$MemberID) { $MemberID = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$Member" -tenantid $TenantId).id } @@ -146,8 +146,8 @@ function Invoke-EditGroup { try { if ($RemoveContact) { $RemoveContact | ForEach-Object { - $Member = $_.value - $MemberID = $_.addedFields.id + $Member = $_.addedFields.userPrincipalName ?? $_.value + $MemberID = $_.value if ($GroupType -eq 'Distribution list' -or $GroupType -eq 'Mail-Enabled Security') { $Params = @{ Identity = $GroupId; Member = $MemberID ; BypassSecurityGroupManagerCheck = $true } $ExoBulkRequests.Add(@{ @@ -174,8 +174,8 @@ function Invoke-EditGroup { try { if ($RemoveMembers) { $RemoveMembers | ForEach-Object { - $Member = $_.value - $MemberID = $_.addedFields.id + $Member = $_.addedFields.userPrincipalName ?? $_.value + $MemberID = $_.value if ($GroupType -eq 'Distribution list' -or $GroupType -eq 'Mail-Enabled Security') { $Params = @{ Identity = $GroupId; Member = $Member ; BypassSecurityGroupManagerCheck = $true } $ExoBulkRequests.Add(@{ @@ -210,8 +210,8 @@ function Invoke-EditGroup { if ($AddOwners) { if ($GroupType -notin @('Distribution List', 'Mail-Enabled Security')) { $AddOwners | ForEach-Object { - $Owner = $_.value - $ID = $_.addedFields.id + $Owner = $_.addedFields.userPrincipalName ?? $_.value + $ID = $_.value $BulkRequests.Add(@{ id = "addOwner-$Owner" @@ -225,7 +225,7 @@ function Invoke-EditGroup { } }) $GraphLogs.Add(@{ - message = "Added $Owner to $($GroupName) group" + message = "Added owner $($Owner) to $($GroupName) group" id = "addOwner-$Owner" }) } @@ -240,14 +240,15 @@ function Invoke-EditGroup { if ($RemoveOwners) { if ($GroupType -notin @('Distribution List', 'Mail-Enabled Security')) { $RemoveOwners | ForEach-Object { - $ID = $_.addedFields.id + $ID = $_.value + $Owner = $_.addedFields.userPrincipalName ?? $_.value $BulkRequests.Add(@{ id = "removeOwner-$ID" method = 'DELETE' url = "groups/$($GroupId)/owners/$ID/`$ref" }) $GraphLogs.Add(@{ - message = "Removed $($_.value) from $($GroupName) group" + message = "Removed owner $($Owner) from $($GroupName) group" id = "removeOwner-$ID" }) } @@ -262,8 +263,8 @@ function Invoke-EditGroup { $NewManagedBy = [System.Collections.Generic.List[string]]::new() foreach ($CurrentOwner in $CurrentOwners) { - if ($RemoveOwners -and $RemoveOwners.addedFields.id -contains $CurrentOwner) { - $OwnerToRemove = $RemoveOwners | Where-Object { $_.addedFields.id -eq $CurrentOwner } + if ($RemoveOwners -and $RemoveOwners.value -contains $CurrentOwner) { + $OwnerToRemove = $RemoveOwners | Where-Object { $_.value -eq $CurrentOwner } $ExoLogs.Add(@{ message = "Removed owner $($OwnerToRemove.label) from $($GroupName) group" target = $GroupId @@ -274,7 +275,7 @@ function Invoke-EditGroup { } if ($AddOwners) { foreach ($NewOwner in $AddOwners) { - $NewManagedBy.Add($NewOwner.addedFields.id) + $NewManagedBy.Add($NewOwner.value) $ExoLogs.Add(@{ message = "Added owner $($NewOwner.label) to $($GroupName) group" target = $GroupId @@ -406,6 +407,28 @@ function Invoke-EditGroup { } } + # Only process hideFromOutlookClients if it was explicitly sent and is a Microsoft 365 group + if ($null -ne $UserObj.hideFromOutlookClients -and $GroupType -eq 'Microsoft 365') { + try { + $Params = @{ Identity = $GroupId; HiddenFromExchangeClientsEnabled = $UserObj.hideFromOutlookClients } + $null = New-ExoRequest -tenantid $TenantId -cmdlet 'Set-UnifiedGroup' -cmdParams $Params -useSystemMailbox $true + + if ($UserObj.hideFromOutlookClients -eq $true) { + $Results.Add("Successfully hidden group mailbox from Outlook for $($GroupName).") + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Successfully hidden group mailbox from Outlook for $($GroupName)." -Sev 'Info' + } else { + $Results.Add("Successfully made group mailbox visible in Outlook for $($GroupName).") + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Successfully made group mailbox visible in Outlook for $($GroupName)." -Sev 'Info' + } + } catch { + $ErrorMessage = Get-CippException -Exception $_ + Write-Warning "Error in hideFromOutlookClients: $($ErrorMessage.NormalizedError) - $($_.InvocationInfo.ScriptLineNumber)" + $action = if ($UserObj.hideFromOutlookClients -eq $true) { 'hide' } else { 'show' } + $Results.Add("Failed to $action group mailbox in Outlook for $($GroupName).") + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantId -message "Failed to $action group mailbox in Outlook for $($GroupName). Error:$($ErrorMessage.NormalizedError)" -Sev 'Error' -LogData $ErrorMessage + } + } + $body = @{'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/Identity/Administration/Groups/Invoke-ListGroups.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Groups/Invoke-ListGroups.ps1 index a516f92158f7..c0256ffdd24a 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 @@ -69,14 +69,14 @@ function Invoke-ListGroups { # get the outside the organization RequireSenderAuthenticationEnabled setting $OnlyAllowInternal = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-DistributionGroup' -cmdParams @{Identity = $GroupID } -Select 'RequireSenderAuthenticationEnabled' -useSystemMailbox $true | Select-Object -ExpandProperty RequireSenderAuthenticationEnabled } elseif ($GroupType -eq 'Microsoft 365') { - $UnifiedGroup = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-UnifiedGroup' -cmdParams @{Identity = $GroupID } -Select 'RequireSenderAuthenticationEnabled,subscriptionEnabled,AutoSubscribeNewMembers' -useSystemMailbox $true - $OnlyAllowInternal = $UnifiedGroup.RequireSenderAuthenticationEnabled + $UnifiedGroupInfo = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-UnifiedGroup' -cmdParams @{Identity = $GroupID } -Select 'RequireSenderAuthenticationEnabled,subscriptionEnabled,AutoSubscribeNewMembers,HiddenFromExchangeClientsEnabled' -useSystemMailbox $true + $OnlyAllowInternal = $UnifiedGroupInfo.RequireSenderAuthenticationEnabled } else { $OnlyAllowInternal = $null } if ($GroupType -eq 'Microsoft 365') { - if ($UnifiedGroup.subscriptionEnabled -eq $true -and $UnifiedGroup.AutoSubscribeNewMembers -eq $true) { $SendCopies = $true } else { $SendCopies = $false } + if ($UnifiedGroupInfo.subscriptionEnabled -eq $true -and $UnifiedGroupInfo.AutoSubscribeNewMembers -eq $true) { $SendCopies = $true } else { $SendCopies = $false } } else { $SendCopies = $null } @@ -85,7 +85,7 @@ function Invoke-ListGroups { if ($BulkRequestArrayList.Count -gt 0) { $RawGraphRequest = New-GraphBulkRequest -tenantid $TenantFilter -scope 'https://graph.microsoft.com/.default' -Requests @($BulkRequestArrayList) -asapp $true $GraphRequest = [PSCustomObject]@{ - groupInfo = ($RawGraphRequest | Where-Object { $_.id -eq 1 }).body | Select-Object *, @{ Name = 'primDomain'; Expression = { $_.mail -split '@' | Select-Object -Last 1 } }, + groupInfo = ($RawGraphRequest | Where-Object { $_.id -eq 1 }).body | Select-Object *, @{ Name = 'primDomain'; Expression = { $_.mail -split '@' | Select-Object -Last 1 } }, @{Name = 'teamsEnabled'; Expression = { if ($_.resourceProvisioningOptions -Like '*Team*') { $true } else { $false } } }, @{Name = 'calculatedGroupType'; Expression = { if ($_.mailEnabled -and $_.securityEnabled) { 'Mail-Enabled Security' } @@ -94,10 +94,11 @@ function Invoke-ListGroups { if (([string]::isNullOrEmpty($_.groupTypes)) -and ($_.mailEnabled) -and (!$_.securityEnabled)) { 'Distribution List' } } }, @{Name = 'dynamicGroupBool'; Expression = { if ($_.groupTypes -contains 'DynamicMembership') { $true } else { $false } } } - members = ($RawGraphRequest | Where-Object { $_.id -eq 2 }).body.value - owners = ($RawGraphRequest | Where-Object { $_.id -eq 3 }).body.value - allowExternal = (!$OnlyAllowInternal) - sendCopies = $SendCopies + members = ($RawGraphRequest | Where-Object { $_.id -eq 2 }).body.value + owners = ($RawGraphRequest | Where-Object { $_.id -eq 3 }).body.value + allowExternal = (!$OnlyAllowInternal) + sendCopies = $SendCopies + hideFromOutlookClients = if ($GroupType -eq 'Microsoft 365') { $UnifiedGroupInfo.HiddenFromExchangeClientsEnabled } else { $null } } } else { $GraphRequest = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/groups/$($GroupID)/$($members)?`$top=999&select=$SelectString" -tenantid $TenantFilter | Select-Object *, @{ Name = 'primDomain'; Expression = { $_.mail -split '@' | Select-Object -Last 1 } }, @@ -128,4 +129,4 @@ function Invoke-ListGroups { Body = $GraphRequest }) -} +} \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-CIPPOffboardingJob.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-CIPPOffboardingJob.ps1 index d0ad323f12f7..0b1c0254759e 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-CIPPOffboardingJob.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-CIPPOffboardingJob.ps1 @@ -11,35 +11,75 @@ function Invoke-CIPPOffboardingJob { if ($Options -is [string]) { $Options = $Options | ConvertFrom-Json } - $userid = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($username)?`$select=id" -tenantid $TenantFilter).id - Write-Host "Running offboarding job for $username with options: $($Options | ConvertTo-Json -Depth 10)" + $User = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($Username)?`$select=id,displayName" -tenantid $TenantFilter + $UserID = $User.id + $DisplayName = $User.displayName + Write-Host "Running offboarding job for $Username with options: $($Options | ConvertTo-Json -Depth 10)" $Return = switch ($Options) { { $_.ConvertToShared -eq $true } { - Set-CIPPMailboxType -Headers $Headers -tenantFilter $TenantFilter -userid $username -username $username -MailboxType 'Shared' -APIName $APIName + try { + Set-CIPPMailboxType -Headers $Headers -tenantFilter $TenantFilter -userid $UserID -username $Username -MailboxType 'Shared' -APIName $APIName + } catch { + $_.Exception.Message + } } { $_.RevokeSessions -eq $true } { - Revoke-CIPPSessions -tenantFilter $TenantFilter -username $username -userid $userid -Headers $Headers -APIName $APIName + try { + Revoke-CIPPSessions -tenantFilter $TenantFilter -username $Username -userid $UserID -Headers $Headers -APIName $APIName + } catch { + $_.Exception.Message + } } { $_.ResetPass -eq $true } { - Set-CIPPResetPassword -tenantFilter $TenantFilter -UserID $username -Headers $Headers -APIName $APIName + try { + Set-CIPPResetPassword -tenantFilter $TenantFilter -DisplayName -UserID $username -Headers $Headers -APIName $APIName + } catch { + $_.Exception.Message + } } { $_.RemoveGroups -eq $true } { - Remove-CIPPGroups -userid $userid -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName -Username "$Username" + Remove-CIPPGroups -userid $UserID -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName -Username $Username } { $_.HideFromGAL -eq $true } { - Set-CIPPHideFromGAL -tenantFilter $TenantFilter -UserID $username -HideFromGAL $true -Headers $Headers -APIName $APIName + try { + Set-CIPPHideFromGAL -tenantFilter $TenantFilter -UserID $username -HideFromGAL $true -Headers $Headers -APIName $APIName + } catch { + $_.Exception.Message + } } { $_.DisableSignIn -eq $true } { - Set-CIPPSignInState -TenantFilter $TenantFilter -userid $username -AccountEnabled $false -Headers $Headers -APIName $APIName + try { + Set-CIPPSignInState -TenantFilter $TenantFilter -userid $username -AccountEnabled $false -Headers $Headers -APIName $APIName + } catch { + $_.Exception.Message + } } { $_.OnedriveAccess } { - $Options.OnedriveAccess | ForEach-Object { Set-CIPPSharePointPerms -tenantFilter $TenantFilter -userid $username -OnedriveAccessUser $_.value -Headers $Headers -APIName $APIName } + $Options.OnedriveAccess | ForEach-Object { + try { + Set-CIPPSharePointPerms -tenantFilter $TenantFilter -userid $username -OnedriveAccessUser $_.value -Headers $Headers -APIName $APIName + } catch { + $_.Exception.Message + } + } } { $_.AccessNoAutomap } { - $Options.AccessNoAutomap | ForEach-Object { Set-CIPPMailboxAccess -tenantFilter $TenantFilter -userid $username -AccessUser $_.value -Automap $false -AccessRights @('FullAccess') -Headers $Headers -APIName $APIName } + $Options.AccessNoAutomap | ForEach-Object { + try { + Set-CIPPMailboxAccess -tenantFilter $TenantFilter -userid $username -AccessUser $_.value -Automap $false -AccessRights @('FullAccess') -Headers $Headers -APIName $APIName + } catch { + $_.Exception.Message + } + } } { $_.AccessAutomap } { - $Options.AccessAutomap | ForEach-Object { Set-CIPPMailboxAccess -tenantFilter $TenantFilter -userid $username -AccessUser $_.value -Automap $true -AccessRights @('FullAccess') -Headers $Headers -APIName $APIName } + $Options.AccessAutomap | ForEach-Object { + try { + Set-CIPPMailboxAccess -tenantFilter $TenantFilter -userid $username -AccessUser $_.value -Automap $true -AccessRights @('FullAccess') -Headers $Headers -APIName $APIName + } catch { + $_.Exception.Message + } + } } { $_.OOO } { try { @@ -50,30 +90,58 @@ function Invoke-CIPPOffboardingJob { } { $_.forward } { if (!$Options.KeepCopy) { - Set-CIPPForwarding -userid $userid -username $username -tenantFilter $TenantFilter -Forward $Options.forward.value -Headers $Headers -APIName $APIName + try { + Set-CIPPForwarding -userid $userid -username $username -tenantFilter $TenantFilter -Forward $Options.forward.value -Headers $Headers -APIName $APIName + } catch { + $_.Exception.Message + } } else { $KeepCopy = [boolean]$Options.KeepCopy - Set-CIPPForwarding -userid $userid -username $username -tenantFilter $TenantFilter -Forward $Options.forward.value -KeepCopy $KeepCopy -Headers $Headers -APIName $APIName + try { + Set-CIPPForwarding -userid $userid -username $username -tenantFilter $TenantFilter -Forward $Options.forward.value -KeepCopy $KeepCopy -Headers $Headers -APIName $APIName + } catch { + $_.Exception.Message + } } } { $_.disableForwarding } { - Set-CIPPForwarding -userid $userid -username $username -tenantFilter $TenantFilter -Disable $true -Headers $Headers -APIName $APIName + try { + Set-CIPPForwarding -userid $userid -username $username -tenantFilter $TenantFilter -Disable $true -Headers $Headers -APIName $APIName + } catch { + $_.Exception.Message + } } { $_.RemoveLicenses -eq $true } { Remove-CIPPLicense -userid $userid -username $Username -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName -Schedule } { $_.DeleteUser -eq $true } { - Remove-CIPPUser -userid $userid -username $Username -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName + try { + Remove-CIPPUser -UserID $userid -Username $Username -TenantFilter $TenantFilter -Headers $Headers -APIName $APIName + } catch { + $_.Exception.Message + } } { $_.RemoveRules -eq $true } { Write-Host "Removing rules for $username" - Remove-CIPPMailboxRule -userid $userid -username $Username -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName -RemoveAllRules + try { + Remove-CIPPMailboxRule -userid $userid -username $Username -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName -RemoveAllRules + } catch { + $_.Exception.Message + } } { $_.RemoveMobile -eq $true } { - Remove-CIPPMobileDevice -userid $userid -username $Username -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName + try { + Remove-CIPPMobileDevice -userid $userid -username $Username -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName + } catch { + $_.Exception.Message + } } { $_.removeCalendarInvites -eq $true } { - Remove-CIPPCalendarInvites -userid $userid -username $Username -tenantFilter $TenantFilter -Headers $Headers -APIName $APIName + try { + Remove-CIPPCalendarInvites -UserID $userid -Username $Username -TenantFilter $TenantFilter -Headers $Headers -APIName $APIName + } catch { + $_.Exception.Message + } } { $_.removePermissions } { if ($RunScheduled) { @@ -99,11 +167,19 @@ function Invoke-CIPPOffboardingJob { "Removal of permissions queued. This task will run in the background and send it's results to the logbook." } } - { $_.'RemoveMFADevices' } { - Remove-CIPPUserMFA -UserPrincipalName $Username -TenantFilter $TenantFilter -Headers $Headers + { $_.RemoveMFADevices -eq $true } { + try { + Remove-CIPPUserMFA -UserPrincipalName $Username -TenantFilter $TenantFilter -Headers $Headers + } catch { + $_.Exception.Message + } } - { $_.'ClearImmutableId' -eq $true } { - Clear-CIPPImmutableID -UserID $userid -TenantFilter $TenantFilter -Headers $Headers -APIName $APIName + { $_.ClearImmutableId -eq $true } { + try { + Clear-CIPPImmutableID -UserID $userid -TenantFilter $TenantFilter -Headers $Headers -APIName $APIName + } catch { + $_.Exception.Message + } } } return $Return 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 5b985cf0817e..f5fd50105a6d 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 @@ -148,19 +148,19 @@ function Invoke-EditUser { } $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($UserObj.id)" -tenantid $UserObj.tenantFilter -type 'patch' -body "{`"mail`": `"$UserPrincipalName`"}" -Verbose Write-LogMessage -API $APIName -tenant ($UserObj.tenantFilter) -headers $Headers -message "Added Aliases to $($UserObj.DisplayName)" -Sev Info - $null = $Results.Add( 'Success. Added aliases to user.') + $Results.Add( 'Success. Added aliases to user.') } } catch { $ErrorMessage = Get-CippException -Exception $_ $Message = "Failed to add aliases to user $($UserObj.DisplayName). Error: $($ErrorMessage.NormalizedError)" Write-LogMessage -API $APIName -tenant ($UserObj.tenantFilter) -headers $Headers -message $Message -Sev Error -LogData $ErrorMessage - $null = $Results.Add($Message) + $Results.Add($Message) } if ($Request.Body.CopyFrom.value) { $CopyFrom = Set-CIPPCopyGroupMembers -Headers $Headers -CopyFromId $Request.Body.CopyFrom.value -UserID $UserPrincipalName -TenantFilter $UserObj.tenantFilter - $null = $Results.AddRange(@($CopyFrom)) + $Results.AddRange(@($CopyFrom)) } if ($AddToGroups) { @@ -185,12 +185,12 @@ function Invoke-EditUser { $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$GroupID/members/`$ref" -tenantid $UserObj.tenantFilter -type POST -body $UserBodyJSON -Verbose } Write-LogMessage -headers $Headers -API $APIName -tenant $UserObj.tenantFilter -message "Added $($UserObj.DisplayName) to $GroupName group" -Sev Info - $null = $Results.Add("Success. $($UserObj.DisplayName) has been added to $GroupName") + $Results.Add("Success. $($UserObj.DisplayName) has been added to $GroupName") } catch { $ErrorMessage = Get-CippException -Exception $_ $Message = "Failed to add member $($UserObj.DisplayName) to $GroupName. Error: $($ErrorMessage.NormalizedError)" Write-LogMessage -headers $Headers -API $APIName -tenant $UserObj.tenantFilter -message $Message -Sev Error -LogData $ErrorMessage - $null = $Results.Add($Message) + $Results.Add($Message) } } } @@ -213,12 +213,12 @@ function Invoke-EditUser { $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$GroupID/members/$($UserObj.id)/`$ref" -tenantid $UserObj.tenantFilter -type DELETE } Write-LogMessage -headers $Headers -API $APIName -tenant $UserObj.tenantFilter -message "Removed $($UserObj.DisplayName) from $GroupName group" -Sev Info - $null = $Results.Add("Success. $($UserObj.DisplayName) has been removed from $GroupName") + $Results.Add("Success. $($UserObj.DisplayName) has been removed from $GroupName") } catch { $ErrorMessage = Get-CippException -Exception $_ $Message = "Failed to remove member $($UserObj.DisplayName) from $GroupName. Error: $($ErrorMessage.NormalizedError)" Write-LogMessage -headers $Headers -API $APIName -tenant $UserObj.tenantFilter -message $Message -Sev Error -LogData $ErrorMessage - $null = $Results.Add($Message) + $Results.Add($Message) } } } @@ -228,7 +228,7 @@ function Invoke-EditUser { $ManagerBodyJSON = ConvertTo-Json -Compress -Depth 10 -InputObject $ManagerBody $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($UserObj.id)/manager/`$ref" -tenantid $UserObj.tenantFilter -type PUT -body $ManagerBodyJSON -Verbose Write-LogMessage -headers $Headers -API $APIName -tenant $UserObj.tenantFilter -message "Set $($UserObj.DisplayName)'s manager to $($Request.body.setManager.label)" -Sev Info - $null = $Results.Add("Success. Set $($UserObj.DisplayName)'s manager to $($Request.body.setManager.label)") + $Results.Add("Success. Set $($UserObj.DisplayName)'s manager to $($Request.body.setManager.label)") } if ($Request.body.setSponsor.value) { @@ -236,14 +236,13 @@ function Invoke-EditUser { $SponsorBodyJSON = ConvertTo-Json -Compress -Depth 10 -InputObject $SponsorBody $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($UserObj.id)/sponsors/`$ref" -tenantid $UserObj.tenantFilter -type POST -body $SponsorBodyJSON -Verbose Write-LogMessage -headers $Headers -API $APIName -tenant $UserObj.tenantFilter -message "Set $($UserObj.DisplayName)'s sponsor to $($Request.body.setSponsor.label)" -Sev Info - $null = $Results.Add("Success. Set $($UserObj.DisplayName)'s sponsor to $($Request.body.setSponsor.label)") + $Results.Add("Success. Set $($UserObj.DisplayName)'s sponsor to $($Request.body.setSponsor.label)") } - $body = @{'Results' = @($results) } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK - Body = $Body + Body = @{'Results' = @($Results) } }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecBECRemediate.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecBECRemediate.ps1 index 51d8203a77c6..35b068c7a887 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 @@ -19,55 +19,196 @@ function Invoke-ExecBECRemediate { $Username = $Request.Body.username Write-Host $TenantFilter Write-Host $SuspectUser + $Results = try { + $AllResults = [System.Collections.Generic.List[object]]::new() + + # Step 1: Reset Password $Step = 'Reset Password' - Set-CIPPResetPassword -UserID $Username -tenantFilter $TenantFilter -APIName $APIName -Headers $Headers + try { + $PasswordResult = Set-CIPPResetPassword -UserID $Username -tenantFilter $TenantFilter -APIName $APIName -Headers $Headers + $AllResults.Add($PasswordResult) + } catch { + $AllResults.Add([pscustomobject]@{ + resultText = "Failed to reset password: $($_.Exception.Message)" + state = 'error' + }) + } + + # Step 2: Disable Account $Step = 'Disable Account' - Set-CIPPSignInState -userid $Username -AccountEnabled $false -tenantFilter $TenantFilter -APIName $APIName -Headers $Headers + try { + $DisableResult = Set-CIPPSignInState -userid $Username -AccountEnabled $false -tenantFilter $TenantFilter -APIName $APIName -Headers $Headers + $AllResults.Add([pscustomobject]@{ + resultText = $DisableResult + state = if ($DisableResult -like "*WARNING*") { 'warning' } else { 'success' } + }) + } catch { + $AllResults.Add([pscustomobject]@{ + resultText = "Failed to disable account: $($_.Exception.Message)" + state = 'error' + }) + } + + # Step 3: Revoke Sessions $Step = 'Revoke Sessions' - Revoke-CIPPSessions -userid $SuspectUser -username $Username -Headers $Headers -APIName $APIName -tenantFilter $TenantFilter + try { + $SessionResult = Revoke-CIPPSessions -userid $SuspectUser -username $Username -Headers $Headers -APIName $APIName -tenantFilter $TenantFilter + $AllResults.Add([pscustomobject]@{ + resultText = $SessionResult + state = if ($SessionResult -like "*Failed*") { 'error' } else { 'success' } + }) + } catch { + $AllResults.Add([pscustomobject]@{ + resultText = "Failed to revoke sessions: $($_.Exception.Message)" + state = 'error' + }) + } + + # Step 4: Remove MFA methods $Step = 'Remove MFA methods' - Remove-CIPPUserMFA -UserPrincipalName $Username -TenantFilter $TenantFilter -Headers $Headers + try { + $MFAResult = Remove-CIPPUserMFA -UserPrincipalName $Username -TenantFilter $TenantFilter -Headers $Headers + $AllResults.Add([pscustomobject]@{ + resultText = $MFAResult + state = if ($MFAResult -like "*No MFA methods*") { 'info' } elseif ($MFAResult -like "*Successfully*") { 'success' } else { 'error' } + }) + } catch { + $AllResults.Add([pscustomobject]@{ + resultText = "Failed to remove MFA methods: $($_.Exception.Message)" + state = 'error' + }) + } + + # Step 5: Disable Inbox Rules $Step = 'Disable Inbox Rules' - $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" - $RuleDisabled++ - } catch { - "Failed to disable Inbox Rule '$($_.Identity)' for $Username" - $RuleFailed++ + try { + Write-LogMessage -headers $Headers -API $APIName -message "Starting inbox rules processing for user: $Username" -Sev 'Info' -tenant $TenantFilter + $Rules = New-ExoRequest -anchor $Username -tenantid $TenantFilter -cmdlet 'Get-InboxRule' -cmdParams @{Mailbox = $Username; IncludeHidden = $true } + Write-LogMessage -headers $Headers -API $APIName -message "Retrieved $(($Rules | Measure-Object).Count) total rules for $Username" -Sev 'Info' -tenant $TenantFilter + $RuleDisabled = 0 + $RuleFailed = 0 + $DelegateRulesSkipped = 0 + $RuleMessages = [System.Collections.Generic.List[string]]::new() + + if (($Rules | Measure-Object).Count -eq 0) { + # No rules exist at all + $AllResults.Add([pscustomobject]@{ + resultText = "No Inbox Rules found for $Username." + state = 'info' + }) + } else { + # Rules exist, filter and process them + $ProcessableRules = $Rules | Where-Object { + $_.Name -ne 'Junk E-Mail Rule' -and + $_.Name -notlike 'Microsoft.Exchange.OOF.*' + } + + if (($ProcessableRules | Measure-Object).Count -eq 0) { + # Rules exist but none are processable after filtering + $SystemRulesCount = ($Rules | Measure-Object).Count - $DelegateRulesSkipped + if ($SystemRulesCount -gt 0) { + $AllResults.Add([pscustomobject]@{ + resultText = "Found $(($Rules | Measure-Object).Count) inbox rules for $Username, but none require disabling (only system rules found)." + state = 'info' + }) + } + } else { + # Process the filterable rules + $ProcessableRules | ForEach-Object { + $CurrentRule = $_ + Write-LogMessage -headers $Headers -API $APIName -message "Processing rule: Name='$($CurrentRule.Name)', Identity='$($CurrentRule.Identity)'" -Sev 'Info' -tenant $TenantFilter + + try { + Set-CIPPMailboxRule -Username $Username -TenantFilter $TenantFilter -RuleId $CurrentRule.Identity -RuleName $CurrentRule.Name -Disable -APIName $APIName -Headers $Headers + + Write-LogMessage -headers $Headers -API $APIName -message "Successfully disabled rule: $($CurrentRule.Name)" -Sev 'Info' -tenant $TenantFilter + $RuleDisabled++ + } catch { + # Check if this is a system delegate rule, if so we can ignore the error + if ($CurrentRule.Name -match '^Delegate Rule -\d+$') { + Write-LogMessage -headers $Headers -API $APIName -message "Skipping delegate rule '$($CurrentRule.Name)' - unable to disable (expected behavior)" -Sev 'Info' -tenant $TenantFilter + $DelegateRulesSkipped++ + } else { + # Handle as normal error + $ErrorMsg = "Could not disable rule '$($CurrentRule.Name)': $($_.Exception.Message)" + Write-LogMessage -headers $Headers -API $APIName -message $ErrorMsg -Sev 'Error' -tenant $TenantFilter + $RuleMessages.Add($ErrorMsg) + $RuleFailed++ + } + } + } + + # Report results + if ($RuleDisabled -gt 0) { + $AllResults.Add([pscustomobject]@{ + resultText = "Successfully disabled $RuleDisabled inbox rules for $Username" + state = 'success' + }) + } elseif ($DelegateRulesSkipped -gt 0 -and $RuleDisabled -eq 0 -and $RuleFailed -eq 0) { + # Only system rules were found, report as no processable rules + $AllResults.Add([pscustomobject]@{ + resultText = "No processable inbox rules found for $Username" + state = 'info' + }) + } + + if ($RuleFailed -gt 0) { + $AllResults.Add([pscustomobject]@{ + resultText = "Failed to process $RuleFailed inbox rules for $Username" + state = 'warning' + }) + + # Add individual rule failure messages as objects + foreach ($RuleMessage in $RuleMessages) { + $AllResults.Add([pscustomobject]@{ + resultText = $RuleMessage + state = 'error' + }) + } + } } } - } - if ($RuleDisabled -gt 0) { - "Disabled $RuleDisabled Inbox Rules for $Username" - } else { - "No Inbox Rules found for $Username. We have not disabled any rules." - } - if ($RuleFailed -gt 0) { - "Failed to disable $RuleFailed Inbox Rules for $Username" + $TotalProcessed = $RuleDisabled + $RuleFailed + $DelegateRulesSkipped + Write-LogMessage -headers $Headers -API $APIName -message "Completed inbox rules processing for $Username. Total rules: $(($Rules | Measure-Object).Count), Processed: $TotalProcessed, Disabled: $RuleDisabled, Failed: $RuleFailed, Delegate rules skipped: $DelegateRulesSkipped" -Sev 'Info' -tenant $TenantFilter + + } catch { + $ErrorMsg = "Failed to process inbox rules: $($_.Exception.Message)" + Write-LogMessage -headers $Headers -API $APIName -message $ErrorMsg -Sev 'Error' -tenant $TenantFilter + $AllResults.Add([pscustomobject]@{ + resultText = $ErrorMsg + state = 'error' + }) } + $StatusCode = [HttpStatusCode]::OK - Write-LogMessage -API 'BECRemediate' -tenant $TenantFilter -message "Executed Remediation for $Username" -sev 'Info' -LogData @($Results) + Write-LogMessage -API 'BECRemediate' -tenant $TenantFilter -message "Executed Remediation for $Username" -sev 'Info' -LogData @($AllResults) + + # Return the results array + $AllResults.ToArray() } catch { $ErrorMessage = Get-CippException -Exception $_ - $Results = [pscustomobject]@{'Results' = "Failed to execute remediation. $($ErrorMessage.NormalizedError)" } + $ErrorList = [System.Collections.Generic.List[object]]::new() + $ErrorList.Add([pscustomobject]@{ + resultText = "Failed to execute remediation at step '$Step'. $($ErrorMessage.NormalizedError)" + state = 'error' + }) Write-LogMessage -API 'BECRemediate' -tenant $TenantFilter -message "Executed Remediation for $Username failed at the $Step step" -sev 'Error' -LogData $ErrorMessage $StatusCode = [HttpStatusCode]::InternalServerError + + # Return the error array + $ErrorList.ToArray() } - $Results = [pscustomobject]@{'Results' = @($Results) } - # Associate values to output bindings by calling 'Push-OutputBinding'. + # Create the final response structure + $ResponseBody = [pscustomobject]@{'Results' = @($Results) } + + # Associate values to output bindings Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = $StatusCode - Body = $Results + Body = $ResponseBody }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDisableUser.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDisableUser.ps1 index c1e6748b7f32..d521b371535c 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDisableUser.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecDisableUser.ps1 @@ -22,7 +22,6 @@ Function Invoke-ExecDisableUser { try { $Result = Set-CIPPSignInState -UserID $ID -TenantFilter $TenantFilter -APIName $APIName -Headers $Headers -AccountEnabled $Enable - if ($Result -like 'Could not disable*' -or $Result -like 'WARNING: User is AD Sync enabled*') { throw $Result } $StatusCode = [HttpStatusCode]::OK } catch { $Result = $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetMFA.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetMFA.ps1 index a72a7f82e40e..0755de89c493 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetMFA.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-ExecResetMFA.ps1 @@ -19,7 +19,6 @@ Function Invoke-ExecResetMFA { $UserID = $Request.Query.ID ?? $Request.Body.ID try { $Result = Remove-CIPPUserMFA -UserPrincipalName $UserID -TenantFilter $TenantFilter -Headers $Headers - if ($Result -match '^Failed') { throw $Result } $StatusCode = [HttpStatusCode]::OK } catch { $Result = $_.Exception.Message 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 d2080b726ab8..879a7b65b432 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 @@ -24,7 +24,6 @@ Function Invoke-ExecResetPass { try { $Result = Set-CIPPResetPassword -UserID $ID -tenantFilter $TenantFilter -APIName $APIName -Headers $Headers -forceChangePasswordNextSignIn $MustChange -DisplayName $DisplayName - if ($Result.state -eq 'Error') { throw $Result.resultText } $StatusCode = [HttpStatusCode]::OK } catch { $Result = $_.Exception.Message 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 4d39d67fbbec..54af83616810 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 @@ -20,8 +20,7 @@ Function Invoke-ExecRevokeSessions { $Username = $Request.Query.Username ?? $Request.Body.Username try { - $Result = Revoke-CIPPSessions -UserID $ID -TenantFilter $TenantFilter -Username $Username -APIName $APIName -Headers $Request.Headers - if ($Result -match '^Failed') { throw $Result } + $Result = Revoke-CIPPSessions -UserID $ID -TenantFilter $TenantFilter -Username $Username -APIName $APIName -Headers $Headers $StatusCode = [HttpStatusCode]::OK } catch { $Result = $_.Exception.Message 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 901678b7b6ea..1cfbd218703c 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 @@ -17,15 +17,31 @@ function Invoke-ListUserSettings { try { $Table = Get-CippTable -tablename 'UserSettings' - $UserSettings = Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq 'allUsers'" - if (!$UserSettings) { $UserSettings = Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq '$Username'" } - $UserSettings = $UserSettings.JSON | ConvertFrom-Json -Depth 10 -ErrorAction SilentlyContinue + $UserSettings = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq 'UserSettings' and RowKey eq 'allUsers'" + if (!$UserSettings) { $UserSettings = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq 'UserSettings' and RowKey eq '$Username'" } + + try { + $UserSettings = $UserSettings.JSON | ConvertFrom-Json -Depth 10 -ErrorAction SilentlyContinue + } catch { + Write-Warning "Failed to convert UserSettings JSON: $($_.Exception.Message)" + $UserSettings = [pscustomobject]@{ + direction = 'ltr' + paletteMode = 'light' + currentTheme = @{ value = 'light'; label = 'light' } + pinNav = $true + showDevtools = $false + customBranding = @{ + colour = '#F77F00' + logo = $null + } + } + } #Get branding settings if ($UserSettings) { $brandingTable = Get-CippTable -tablename 'Config' - $BrandingSettings = Get-CIPPAzDataTableEntity @brandingTable -Filter "RowKey eq 'BrandingSettings'" + $BrandingSettings = Get-CIPPAzDataTableEntity @brandingTable -Filter "PartitionKey eq 'BrandingSettings' and RowKey eq 'BrandingSettings'" if ($BrandingSettings) { - $UserSettings | Add-Member -MemberType NoteProperty -Name 'BrandingSettings' -Value $BrandingSettings -Force | Out-Null + $UserSettings | Add-Member -MemberType NoteProperty -Name 'customBranding' -Value $BrandingSettings -Force | Out-Null } } $StatusCode = [HttpStatusCode]::OK diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-RemoveUser.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-RemoveUser.ps1 index 6b5db1ad6733..48d7379aaf71 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-RemoveUser.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-RemoveUser.ps1 @@ -17,21 +17,15 @@ Function Invoke-RemoveUser { # Interact with query parameters or the body of the request. $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter $UserID = $Request.Query.ID ?? $Request.Body.ID - $UserPrincipalName = $Request.Query.userPrincipalName ?? $Request.Body.userPrincipalName + $Username = $Request.Query.userPrincipalName ?? $Request.Body.userPrincipalName if (!$UserID) { exit } try { - $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($UserID)" -type DELETE -tenant $TenantFilter - $Result = "Successfully deleted user with ID: '$UserID'" - if ($UserPrincipalName) { $Result += " and User Principal Name: '$UserPrincipalName'" } - Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev 'Info' -tenant $TenantFilter + $Result = Remove-CIPPUser -UserID $UserID -Username $Username -TenantFilter $TenantFilter -Headers $Headers -APIName $APIName $StatusCode = [HttpStatusCode]::OK } catch { - $ErrorMessage = Get-CippException -Exception $_ - $Result = "Failed to delete user $($UserID). $($ErrorMessage.NormalizedError)" - if ($UserPrincipalName) { $Result += " User Principal Name: '$($UserPrincipalName)'" } - Write-LogMessage -Headers $Headers -API $APIName -message $Result -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + $Result = $_.Exception.Message $StatusCode = [HttpStatusCode]::InternalServerError } 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 13eb06e766b1..8f720dc32a19 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 @@ -1,6 +1,6 @@ using namespace System.Net -Function Invoke-AddSite { +function Invoke-AddSite { <# .FUNCTIONALITY Entrypoint @@ -24,7 +24,7 @@ Function Invoke-AddSite { $StatusCode = [HttpStatusCode]::OK } catch { $StatusCode = [HttpStatusCode]::InternalServerError - $Result = "Failed to create SharePoint Site: $($_.Exception.Message)" + $Result = $_.Exception.Message } # Associate values to output bindings by calling 'Push-OutputBinding'. diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSetSharePointMember.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSetSharePointMember.ps1 index 3d8e9947ff77..0ac9be97d022 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSetSharePointMember.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ExecSetSharePointMember.ps1 @@ -1,6 +1,6 @@ using namespace System.Net -Function Invoke-ExecSetSharePointMember { +function Invoke-ExecSetSharePointMember { <# .FUNCTIONALITY Entrypoint @@ -27,6 +27,7 @@ Function Invoke-ExecSetSharePointMember { $UserID = (New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/users/$($Request.Body.user.value)" -tenantid $TenantFilter).id $Results = Remove-CIPPGroupMember -GroupType 'Team' -GroupID $GroupID -Member $UserID -TenantFilter $TenantFilter -Headers $Headers } + $StatusCode = [HttpStatusCode]::OK } else { $StatusCode = [HttpStatusCode]::BadRequest $Results = 'This type of SharePoint site is not supported.' 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 a35801474473..7f7b4c72911f 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 @@ -16,14 +16,15 @@ function Invoke-ListTeamsVoice { # Interact with query parameters or the body of the request. $TenantFilter = $Request.Query.tenantFilter - $TenantId = (Get-Tenants | Where-Object -Property defaultDomainName -EQ $TenantFilter).customerId + $TenantId = (Get-Tenants -TenantFilter $TenantFilter).customerId try { $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 'Reached the loop' + $Results = 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 + #Write-Information ($Results | ConvertTo-Json -Depth 10) + $data = $Results.TelephoneNumbers | ForEach-Object { $CompleteRequest = $_ | Select-Object *, @{Name = 'AssignedTo'; Expression = { $users | Where-Object -Property id -EQ $_.TargetId } } if ($CompleteRequest.AcquisitionDate) { $CompleteRequest.AcquisitionDate = $_.AcquisitionDate -split 'T' | Select-Object -First 1 @@ -33,11 +34,9 @@ function Invoke-ListTeamsVoice { $CompleteRequest.AssignedTo ? $null : ($CompleteRequest | Add-Member -NotePropertyName 'AssignedTo' -NotePropertyValue 'Unassigned' -Force) $CompleteRequest } - Write-Host 'Finished the loop' $Skip = $Skip + 999 $Data } while ($data.Count -eq 999) - Write-Host 'Exiting the Do.' $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message @@ -48,7 +47,7 @@ function Invoke-ListTeamsVoice { Write-Host 'Returning the response' Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = $StatusCode - Body = @($GraphRequest) + Body = @($GraphRequest | Where-Object { $_.TelephoneNumber }) }) } 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 5cfc332f7ef8..2fd0871a46e3 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 @@ -1,6 +1,6 @@ using namespace System.Net -Function Invoke-ListAlertsQueue { +function Invoke-ListAlertsQueue { <# .FUNCTIONALITY Entrypoint @@ -70,11 +70,40 @@ Function Invoke-ListAlertsQueue { $ExcludedTenants = @() } + # Handle tenant group display information for alerts + $TenantsForDisplay = @() + if ($Task.TenantGroup) { + try { + $TenantGroupObject = $Task.TenantGroup | ConvertFrom-Json -ErrorAction SilentlyContinue + if ($TenantGroupObject) { + # Create a tenant group object for display + $TenantGroupForDisplay = [PSCustomObject]@{ + label = $TenantGroupObject.label + value = $TenantGroupObject.value + type = 'Group' + } + $TenantsForDisplay = @($TenantGroupForDisplay) + } + } catch { + Write-Warning "Failed to parse tenant group information for alert task $($Task.RowKey): $($_.Exception.Message)" + # Fall back to regular tenant display + $TenantsForDisplay = @($Task.Tenant) + } + } else { + # For regular tenants, create a tenant object for consistent formatting + $TenantForDisplay = [PSCustomObject]@{ + label = $Task.Tenant + value = $Task.Tenant + type = 'Tenant' + } + $TenantsForDisplay = @($TenantForDisplay) + } + $TaskEntry = [PSCustomObject]@{ RowKey = $Task.RowKey PartitionKey = $Task.PartitionKey excludedTenants = @($ExcludedTenants) - Tenants = @($Task.Tenant) + Tenants = $TenantsForDisplay Conditions = $Task.Name Actions = $Task.PostExecution LogType = 'Scripted' @@ -82,10 +111,46 @@ Function Invoke-ListAlertsQueue { RepeatsEvery = $Task.Recurrence RawAlert = $Task } + if ($AllowedTenants -notcontains 'AllTenants') { - $Tenant = $TenantList | Where-Object -Property defaultDomainName -EQ $Task.Tenant - if ($AllowedTenants -contains $Tenant.customerId) { - $AllTasksArrayList.Add($TaskEntry) + # For tenant groups, we need to expand and check access + if ($Task.TenantGroup) { + try { + $TenantGroupObject = $Task.TenantGroup | ConvertFrom-Json -ErrorAction SilentlyContinue + if ($TenantGroupObject) { + # Create a tenant filter object for expansion + $TenantFilterForExpansion = @([PSCustomObject]@{ + type = 'Group' + value = $TenantGroupObject.value + label = $TenantGroupObject.label + }) + + # Expand the tenant group to individual tenants + $ExpandedTenants = Expand-CIPPTenantGroups -TenantFilter $TenantFilterForExpansion + + # Check if user has access to any tenant in the group + $HasAccess = $false + foreach ($ExpandedTenant in $ExpandedTenants) { + $TenantInfo = $TenantList | Where-Object -Property defaultDomainName -EQ $ExpandedTenant.value + if ($TenantInfo -and $AllowedTenants -contains $TenantInfo.customerId) { + $HasAccess = $true + break + } + } + + if ($HasAccess) { + $AllTasksArrayList.Add($TaskEntry) + } + } + } catch { + Write-Warning "Failed to expand tenant group for access check: $($_.Exception.Message)" + } + } else { + # Regular tenant access check + $Tenant = $TenantList | Where-Object -Property defaultDomainName -EQ $Task.Tenant + if ($AllowedTenants -contains $Tenant.customerId) { + $AllTasksArrayList.Add($TaskEntry) + } } } else { $AllTasksArrayList.Add($TaskEntry) diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecApplication.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecApplication.ps1 new file mode 100644 index 000000000000..c46541d8632f --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecApplication.ps1 @@ -0,0 +1,155 @@ +function Invoke-ExecApplication { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Tenant.Application.ReadWrite + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + $ValidTypes = @('applications', 'servicePrincipals') + $ValidActions = @('Update', 'Upsert', 'Delete', 'RemoveKey', 'RemovePassword') + + $Id = $Request.Query.Id ?? $Request.Body.Id + $Type = $Request.Query.Type ?? $Request.Body.Type + if (-not $Id) { + $AppId = $Request.Query.AppId ?? $Request.Body.AppId + if (-not $AppId) { + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::BadRequest + Body = "Required parameter 'Id' or 'AppId' is missing" + }) + return + } + $IdPath = "(appId='$AppId')" + } else { + $IdPath = "/$Id" + } + if ($Type -and $ValidTypes -notcontains $Type) { + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::BadRequest + Body = "Invalid Type specified. Valid types are: $($ValidTypes -join ', ')" + }) + return + } + + $Uri = "https://graph.microsoft.com/beta/$($Type)$($IdPath)" + $Action = $Request.Query.Action ?? $Request.Body.Action + + if ($ValidActions -notcontains $Action) { + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::BadRequest + Body = "Invalid Action specified. Valid actions are: $($ValidActions -join ', ')" + }) + return + } + + $PostParams = @{ + Uri = $Uri + } + + if ($Action -eq 'Delete') { + $PostParams.Type = 'DELETE' + } + if ($Action -eq 'Update' -or $Action -eq 'Upsert') { + $PostParams.Type = 'PATCH' + } + + if ($Action -eq 'Upsert') { + $PostParams.AddedHeaders = @{ + 'Prefer' = 'create-if-missing' + } + } + + if ($Request.Body) { + $PostParams.Body = $Request.Body.Payload | ConvertTo-Json -Compress + } + + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + + try { + if ($Action -eq 'RemoveKey' -or $Action -eq 'RemovePassword') { + # Handle credential removal + $KeyIds = $Request.Body.KeyIds.value ?? $Request.Body.KeyIds + if (-not $KeyIds -or $KeyIds.Count -eq 0) { + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::BadRequest + Body = "KeyIds parameter is required for $Action action" + }) + return + } + + if ($Action -eq 'RemoveKey') { + # For key credentials, use a single PATCH request + $CurrentObject = New-GraphGetRequest -Uri $Uri -tenantid $TenantFilter -AsApp $true + $UpdatedKeyCredentials = $CurrentObject.keyCredentials | Where-Object { $_.keyId -notin $KeyIds } + $PatchBody = @{ + keyCredentials = @($UpdatedKeyCredentials) + } + + $Response = New-GraphPOSTRequest -Uri $Uri -Type 'PATCH' -Body ($PatchBody | ConvertTo-Json -Depth 10) -tenantid $TenantFilter -AsApp $true + + $Results = @{ + resultText = "Successfully removed $($KeyIds.Count) key credential(s) from $Type" + state = 'success' + details = @($Response) + } + } else { + # For password credentials, use bulk removePassword requests + $BulkRequests = foreach ($KeyId in $KeyIds) { + $RemoveBody = @{ + keyId = $KeyId + } + + @{ + id = $KeyId + method = 'POST' + url = "$($Type)$($IdPath)/removePassword" + body = $RemoveBody + headers = @{ + 'Content-Type' = 'application/json' + } + } + } + + $BulkResults = New-GraphBulkRequest -Requests @($BulkRequests) -tenantid $TenantFilter -AsApp $true + + $SuccessCount = ($BulkResults | Where-Object { $_.status -eq 204 }).Count + $FailureCount = ($BulkResults | Where-Object { $_.status -ne 204 }).Count + + $Results = @{ + resultText = "Bulk RemovePassword completed. Success: $SuccessCount, Failures: $FailureCount" + state = if ($FailureCount -eq 0) { 'success' } else { 'error' } + details = @($BulkResults) + } + } + } else { + # Handle regular actions + $null = New-GraphPOSTRequest @PostParams -tenantid $TenantFilter -AsApp $true + $Results = @{ + resultText = "Successfully executed $Action on $Type with Id: $Id" + state = 'success' + } + } + + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = @{ Results = $Results } + }) + } catch { + $Results = @{ + resultText = "Failed to execute $Action on $Type with Id: $Id. Error: $($_.Exception.Message)" + state = 'error' + } + + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::InternalServerError + Body = @{ Results = @($Results) } + }) + } +} diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListAppConsentRequests.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListAppConsentRequests.ps1 index 89472cd5821a..0029cf95e0ba 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListAppConsentRequests.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Invoke-ListAppConsentRequests.ps1 @@ -15,13 +15,33 @@ function Invoke-ListAppConsentRequests { # Interact with query parameters or the body of the request. $TenantFilter = $Request.Query.tenantFilter + $RequestStatus = $Request.Query.RequestStatus + $Filter = $Request.Query.Filter try { if ($TenantFilter -eq 'AllTenants') { throw 'AllTenants is not yet supported' } - $appConsentRequests = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/identityGovernance/appConsent/appConsentRequests' -tenantid $TenantFilter # Need the beta endpoint to get consentType + # Apply server-side filtering if requested + $Uri = 'https://graph.microsoft.com/beta/identityGovernance/appConsent/appConsentRequests' # Need the beta endpoint to get consentType + if ($Filter -eq $true -and $RequestStatus) { + switch ($RequestStatus) { + 'InProgress' { + $FilterQuery = "userConsentRequests/any (u:u/status eq '$RequestStatus')" + $Uri = "$Uri`?`$filter=$([System.Web.HttpUtility]::UrlEncode($FilterQuery))" + Write-Host "Applying server-side filter for RequestStatus: $RequestStatus" + $ServerSideFilteringApplied = $true + } + default { + # All the other values are not supported yet even if the Graph API docs say they are. -Bobby + $ServerSideFilteringApplied = $false + } + } + } + + $appConsentRequests = New-GraphGetRequest -Uri $Uri -tenantid $TenantFilter + $Results = foreach ($app in $appConsentRequests) { $userConsentRequests = New-GraphGetRequest -Uri "https://graph.microsoft.com/v1.0/identityGovernance/appConsent/appConsentRequests/$($app.id)/userConsentRequests" -tenantid $TenantFilter $userConsentRequests | ForEach-Object { @@ -48,12 +68,19 @@ function Invoke-ListAppConsentRequests { } } } + + # Apply filtering if requested. Has to be done before and after the foreach loop, as the serverside filter is only supported for InProgress. + if ($Filter -eq $true -and $ServerSideFilteringApplied -eq $false) { + if ($RequestStatus) { + Write-Host "Filtering by RequestStatus: $RequestStatus" + $Results = $Results | Where-Object { $_.requestStatus -eq $RequestStatus } + } + } $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-CippException -Exception $_ $StatusCode = [HttpStatusCode]::InternalServerError - Write-LogMessage -Headers $Headers -API $APIName -message 'app consent request list failed' -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - $Results = @{ appDisplayName = "Error: $($ErrorMessage.NormalizedError)" } + $Results = "Error: $($ErrorMessage.NormalizedError)" } Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ 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 fc6fa8b523f3..bd5c6e397f4b 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 @@ -1,6 +1,6 @@ using namespace System.Net -Function Invoke-AddCAPolicy { +function Invoke-AddCAPolicy { <# .FUNCTIONALITY Entrypoint @@ -19,7 +19,7 @@ Function Invoke-AddCAPolicy { $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 $Headers + $CAPolicy = New-CIPPCAPolicy -replacePattern $Request.Body.replacename -Overwrite $request.Body.overwrite -TenantFilter $Tenant -state $Request.Body.NewState -DisableSD $Request.Body.DisableSD -RawJSON $Request.Body.RawJSON -APIName $APIName -Headers $Headers "$CAPolicy" } catch { "$($_.Exception.Message)" 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 758b92eaef24..3ff15b901e71 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 @@ -1,6 +1,6 @@ using namespace System.Net -Function Invoke-ExecCAExclusion { +function Invoke-ExecCAExclusion { <# .FUNCTIONALITY Entrypoint @@ -13,48 +13,87 @@ Function Invoke-ExecCAExclusion { $APIName = $Request.Params.CIPPEndpoint $Headers = $Request.Headers Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + try { + #If UserId is a guid, get the user's UPN + $TenantFilter = $Request.Body.tenantFilter + $UserID = $Request.Body.UserID + $Username = $Request.Body.Username + $Users = $Request.Body.Users + $EndDate = $Request.Body.EndDate + $PolicyId = $Request.Body.PolicyId + $ExclusionType = $Request.Body.ExclusionType - #If UserId is a guid, get the user's UPN - $TenantFilter = $Request.Body.tenantFilter - $UserId = $Request.Body.UserID - $EndDate = $Request.Body.EndDate - $PolicyId = $Request.Body.PolicyId - $ExclusionType = $Request.Body.ExclusionType + if ($Users) { + $UserID = $Users.value + $Username = $Users.addedFields.userPrincipalName -join ', ' + } else { + if ($UserID -match '^[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}$' -and -not $Username) { + $Username = (New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/users/$($UserID)" -tenantid $TenantFilter).userPrincipalName + } + } + $Policy = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/identity/conditionalAccess/policies/$($PolicyId)?`$select=id,displayName" -tenantid $TenantFilter -asApp $true - 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 - $EndDate = $Request.Body.EndDate - $TaskBody = [pscustomobject]@{ - TenantFilter = $TenantFilter - Name = "Add CA Exclusion Vacation Mode: $Username - $($TenantFilter)" - Command = @{ - value = 'Set-CIPPCAExclusion' - label = 'Set-CIPPCAExclusion' - } - Parameters = [pscustomobject]@{ + if (-not $Policy) { + throw "Policy with ID $PolicyId not found in tenant $TenantFilter." + } + + $PolicyName = $Policy.displayName + if ($Request.Body.vacation -eq 'true') { + $StartDate = $Request.Body.StartDate + $EndDate = $Request.Body.EndDate + + $Parameters = [PSCustomObject]@{ ExclusionType = 'Add' - UserID = $UserID PolicyId = $PolicyId - UserName = $Username } - ScheduledTime = $StartDate + + if ($Users) { + $Parameters | Add-Member -NotePropertyName Users -NotePropertyValue $Users + } else { + $Parameters | Add-Member -NotePropertyName UserID -NotePropertyValue $UserID + } + + $TaskBody = [pscustomobject]@{ + TenantFilter = $TenantFilter + Name = "Add CA Exclusion Vacation Mode: $PolicyName" + Command = @{ + value = 'Set-CIPPCAExclusion' + label = 'Set-CIPPCAExclusion' + } + Parameters = [pscustomobject]$Parameters + ScheduledTime = $StartDate + } + + Write-Information ($TaskBody | ConvertTo-Json -Depth 10) + + Add-CIPPScheduledTask -Task $TaskBody -hidden $false + #Removal of the exclusion + $TaskBody.Parameters.ExclusionType = 'Remove' + $TaskBody.Name = "Remove CA Exclusion Vacation Mode: $PolicyName" + $TaskBody.ScheduledTime = $EndDate + Add-CIPPScheduledTask -Task $TaskBody -hidden $false + $body = @{ Results = "Successfully added vacation mode schedule for $Username." } + } else { + $Parameters = @{ + ExclusionType = $ExclusionType + PolicyId = $PolicyId + } + if ($Users) { + $Parameters.Users = $Users + } else { + $Parameters.UserID = $UserID + } + + Set-CIPPCAExclusion -TenantFilter $TenantFilter -Headers $Headers @Parameters } - Add-CIPPScheduledTask -Task $TaskBody -hidden $false - #Removal of the exclusion - $TaskBody.Parameters.ExclusionType = 'Remove' - $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 $TenantFilter -ExclusionType $ExclusionType -UserID $UserID -PolicyId $PolicyId -Headers $Headers -UserName $Username + } catch { + Write-Warning "Failed to perform exclusion for $Username : $($_.Exception.Message)" + Write-Information $_.InvocationInfo.PositionMessage + $body = @{ Results = "Failed to perform exclusion for $Username : $($_.Exception.Message)" } + Write-LogMessage -headers $Headers -API 'Invoke-ExecCAExclusion' -message "Failed to perform exclusion for $Username : $_" -Sev 'Error' -tenant $TenantFilter -LogData (Get-CippException -Exception $_) } - Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK Body = $Body diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCAServiceExclusion.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCAServiceExclusion.ps1 new file mode 100644 index 000000000000..e5db017bf14e --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Conditional/Invoke-ExecCAServiceExclusion.ps1 @@ -0,0 +1,35 @@ +using namespace System.Net + +Function Invoke-ExecCAServiceExclusion { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Tenant.ConditionalAccess.ReadWrite + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug' + + # Interact with the request + $TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter + $ID = $Request.Query.GUID ?? $Request.Body.GUID + + try { + $result = Set-CIPPCAPolicyServiceException -TenantFilter $TenantFilter -PolicyId $ID + $Body = @{ Results = $result } + Write-LogMessage -headers $Headers -API 'Set-CIPPCAPolicyServiceException' -message $Message -Sev 'Info' -tenant $TenantFilter + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Body = @{ Results = "Failed to add service provider exception to policy $($ID): $($ErrorMessage.NormalizedError)" } + Write-LogMessage -headers $Headers -API 'Set-CIPPCAPolicyServiceException' -message "Failed to update policy $($PolicyId) with service provider exception for tenant $($CSPtenantId): $($_.Exception.Message)" -Sev 'Error' -tenant $TenantFilter -LogData (Get-CippException -Exception $_) + } + + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = $Body + }) +} \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListTenantAlignment.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListTenantAlignment.ps1 new file mode 100644 index 000000000000..4f4a48dd6766 --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Standards/Invoke-ListTenantAlignment.ps1 @@ -0,0 +1,44 @@ +using namespace System.Net + +function Invoke-ListTenantAlignment { + <# + .FUNCTIONALITY + Entrypoint + .ROLE + Tenant.Standards.Read + #> + [CmdletBinding()] + param($Request, $TriggerMetadata) + + $APIName = $Request.Params.CIPPEndpoint + $Headers = $Request.Headers + + try { + # Use the new Get-CIPPTenantAlignment function to get alignment data + $AlignmentData = Get-CIPPTenantAlignment + + # Transform the data to match the expected API response format + $Results = $AlignmentData | ForEach-Object { + [PSCustomObject]@{ + tenantFilter = $_.TenantFilter + standardName = $_.StandardName + standardId = $_.StandardId + alignmentScore = $_.AlignmentScore + LicenseMissingPercentage = $_.LicenseMissingPercentage + combinedAlignmentScore = $_.CombinedScore + latestDataCollection = $_.LatestDataCollection + } + } + + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = @($Results) + }) + } catch { + Write-LogMessage -API $APIName -message "Failed to get tenant alignment data: $($_.Exception.Message)" -sev Error + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::InternalServerError + Body = @{ error = "Failed to get tenant alignment data: $($_.Exception.Message)" } + }) + } +} 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 4b068585ffc6..9828d33ba5ef 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 @@ -13,10 +13,9 @@ function Invoke-ExecGraphExplorerPreset { $APIName = $Request.Params.CIPPEndpoint $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 ?? '' + $Action = $Request.Body.action ?? '' Write-Information ($Request.Body | ConvertTo-Json -Depth 10) @@ -48,8 +47,10 @@ function Invoke-ExecGraphExplorerPreset { Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = $StatusCode Body = @{ - Results = $Message - Success = $false + Results = @{ + resultText = $Message + state = 'error' + } } }) return @@ -61,8 +62,10 @@ function Invoke-ExecGraphExplorerPreset { Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = $StatusCode Body = @{ - Results = $Message - Success = $false + Results = @{ + resultText = $Message + state = 'error' + } } }) return @@ -111,8 +114,10 @@ function Invoke-ExecGraphExplorerPreset { Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = $StatusCode Body = @{ - Results = $Message - Success = $Success + Results = @{ + resultText = $Message + state = if ($Success) { 'success' } else { 'error' } + } } }) } diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecCSPLicense.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecCSPLicense.ps1 index fc6ce44569e4..1f4796422ab2 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecCSPLicense.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecCSPLicense.ps1 @@ -1,11 +1,11 @@ using namespace System.Net -Function Invoke-ExecCSPLicense { +function Invoke-ExecCSPLicense { <# .FUNCTIONALITY Entrypoint .ROLE - Tenant.Directory.Read + Tenant.Directory.ReadWrite #> [CmdletBinding()] param($Request, $TriggerMetadata) @@ -17,7 +17,7 @@ Function Invoke-ExecCSPLicense { # Interact with query parameters or the body of the request. $TenantFilter = $Request.Body.tenantFilter $Action = $Request.Body.Action - $SKU = $Request.Body.SKU + $SKU = $Request.Body.SKU.value ?? $Request.Body.SKU try { if ($Action -eq 'Add') { diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphExplorerPresets.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphExplorerPresets.ps1 index 7f372f03a1e7..60801c2e3afb 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphExplorerPresets.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ListGraphExplorerPresets.ps1 @@ -14,8 +14,7 @@ function Invoke-ListGraphExplorerPresets { $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'] + $Username = ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Headers.'x-ms-client-principal')) | ConvertFrom-Json).userDetails try { $Table = Get-CIPPTable -TableName 'GraphPresets' @@ -26,6 +25,7 @@ function Invoke-ListGraphExplorerPresets { name = $Preset.name IsShared = $Preset.IsShared IsMyPreset = $Preset.Owner -eq $Username + Owner = $Preset.Owner params = (ConvertFrom-Json -InputObject $Preset.Params) } } diff --git a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-UserTasksOrchestrator.ps1 b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-UserTasksOrchestrator.ps1 index 9863866fa438..ab8383486b3d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-UserTasksOrchestrator.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-UserTasksOrchestrator.ps1 @@ -50,7 +50,50 @@ function Start-UserTasksOrchestrator { } } $Batch.AddRange($AllTenantCommands) + } elseif ($task.TenantGroup) { + # Handle tenant groups - expand group to individual tenants + try { + $TenantGroupObject = $task.TenantGroup | ConvertFrom-Json + Write-Host "Expanding tenant group: $($TenantGroupObject.label) with ID: $($TenantGroupObject.value)" + + # Create a tenant filter object for expansion + $TenantFilterForExpansion = @([PSCustomObject]@{ + type = 'Group' + value = $TenantGroupObject.value + label = $TenantGroupObject.label + }) + + # Expand the tenant group to individual tenants + $ExpandedTenants = Expand-CIPPTenantGroups -TenantFilter $TenantFilterForExpansion + + $ExcludedTenants = $task.excludedTenants -split ',' + Write-Host "Excluded Tenants from this task: $ExcludedTenants" + + $GroupTenantCommands = foreach ($ExpandedTenant in $ExpandedTenants | Where-Object { $_.value -notin $ExcludedTenants }) { + $NewParams = $task.Parameters.Clone() + if ((Get-Command $task.Command).Parameters.TenantFilter) { + $NewParams.TenantFilter = $ExpandedTenant.value + } + [pscustomobject]@{ + Command = $task.Command + Parameters = $NewParams + TaskInfo = $task + FunctionName = 'ExecScheduledCommand' + } + } + $Batch.AddRange($GroupTenantCommands) + } catch { + Write-Host "Error expanding tenant group: $($_.Exception.Message)" + Write-LogMessage -API 'Scheduler_UserTasks' -tenant $tenant -message "Failed to expand tenant group for task $($task.Name): $($_.Exception.Message)" -sev Error + + # Fall back to treating as single tenant + if ((Get-Command $task.Command).Parameters.TenantFilter) { + $ScheduledCommand.Parameters['TenantFilter'] = $task.Tenant + } + $Batch.Add($ScheduledCommand) + } } else { + # Handle single tenant if ((Get-Command $task.Command).Parameters.TenantFilter) { $ScheduledCommand.Parameters['TenantFilter'] = $task.Tenant } diff --git a/Modules/CIPPCore/Public/Functions/Get-CIPPTenantAlignment.ps1 b/Modules/CIPPCore/Public/Functions/Get-CIPPTenantAlignment.ps1 new file mode 100644 index 000000000000..5671b2a79632 --- /dev/null +++ b/Modules/CIPPCore/Public/Functions/Get-CIPPTenantAlignment.ps1 @@ -0,0 +1,260 @@ +function Get-CIPPTenantAlignment { + <# + .SYNOPSIS + Gets tenant alignment data for standards compliance + .DESCRIPTION + This function calculates tenant alignment percentages against standards templates. + It processes all standard templates and compares them against tenant standards data. + .PARAMETER TenantFilter + The tenant to get alignment data for. If not specified, processes all tenants. + .PARAMETER TemplateId + Optional specific template GUID to check alignment for. If not specified, processes all templates. + .FUNCTIONALITY + Internal + .EXAMPLE + Get-CIPPTenantAlignment -TenantFilter "contoso.onmicrosoft.com" + .EXAMPLE + Get-CIPPTenantAlignment -TenantFilter "contoso.onmicrosoft.com" -TemplateId "12345-67890-abcdef" + #> + [CmdletBinding()] + param( + [Parameter(Mandatory = $false)] + [string]$TenantFilter, + + [Parameter(Mandatory = $false)] + [string]$TemplateId + ) + + try { + # Get all standard templates + $TemplateTable = Get-CippTable -tablename 'templates' + $TemplateFilter = "PartitionKey eq 'StandardsTemplateV2'" + + $Templates = (Get-CIPPAzDataTableEntity @TemplateTable -Filter $TemplateFilter) | ForEach-Object { + $JSON = $_.JSON -replace '"Action":', '"action":' + try { + $RowKey = $_.RowKey + $Data = $JSON | ConvertFrom-Json -Depth 100 -ErrorAction SilentlyContinue + } catch { + Write-Warning "$($RowKey) standard could not be loaded: $($_.Exception.Message)" + return + } + if ($Data) { + $Data | Add-Member -NotePropertyName 'GUID' -NotePropertyValue $_.GUID -Force + $Data + } + } + + if (-not $Templates) { + Write-Warning 'No templates found matching the criteria' + return @() + } + + # Get standards comparison data + $StandardsTable = Get-CIPPTable -TableName 'CippStandardsReports' + $AllStandards = Get-CIPPAzDataTableEntity @StandardsTable + + # Filter by tenant if specified + $Standards = if ($TenantFilter) { + $AllStandards | Where-Object { $_.PartitionKey -eq $TenantFilter } + } else { + $AllStandards + } + + # Build tenant standards data structure + $TenantStandards = @{} + foreach ($Standard in $Standards) { + $FieldName = $Standard.RowKey + $FieldValue = $Standard.Value + $Tenant = $Standard.PartitionKey + + # Process field value + if ($FieldValue -is [System.Boolean]) { + $FieldValue = [bool]$FieldValue + } elseif ($FieldValue -like '*{*') { + $FieldValue = ConvertFrom-Json -InputObject $FieldValue -ErrorAction SilentlyContinue + } else { + $FieldValue = [string]$FieldValue + } + + if (-not $TenantStandards.ContainsKey($Tenant)) { + $TenantStandards[$Tenant] = @{} + } + $TenantStandards[$Tenant][$FieldName] = @{ + Value = $FieldValue + LastRefresh = $Standard.TimeStamp.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ') + } + } + + $Results = [System.Collections.Generic.List[object]]::new() + + # Process each template against all tenants + foreach ($Template in $Templates) { + $TemplateStandards = $Template.standards + if (-not $TemplateStandards) { + continue + } + + # Check if template has tenant assignments (scope) + $TemplateAssignedTenants = @() + $AppliestoAllTenants = $false + + if ($Template.tenantFilter -and $Template.tenantFilter.Count -gt 0) { + # Extract tenant values from the tenantFilter array + $TenantValues = $Template.tenantFilter | ForEach-Object { $_.value } + + if ($TenantValues -contains 'AllTenants') { + $AppliestoAllTenants = $true + } else { + $TemplateAssignedTenants = $TenantValues + } + } else { + $AppliestoAllTenants = $true + } + + $StandardsData = foreach ($StandardKey in $TemplateStandards.PSObject.Properties.Name) { + $StandardConfig = $TemplateStandards.$StandardKey + $StandardId = "standards.$StandardKey" + + $Actions = @() + if ($StandardConfig.action) { + $Actions = $StandardConfig.action + } elseif ($StandardConfig.Action) { + $Actions = $StandardConfig.Action + } elseif ($StandardConfig.PSObject.Properties['action']) { + $Actions = $StandardConfig.PSObject.Properties['action'].Value + } + + $ReportingEnabled = $false + if ($Actions -and $Actions.Count -gt 0) { + $ReportingEnabled = ($Actions | Where-Object { $_.value -and ($_.value.ToLower() -eq 'report' -or $_.value.ToLower() -eq 'remediate') }).Count -gt 0 + } + + # Handle Intune templates specially + if ($StandardKey -eq 'IntuneTemplate' -and $StandardConfig -is [array]) { + foreach ($IntuneTemplate in $StandardConfig) { + if ($IntuneTemplate.TemplateList.value) { + $IntuneStandardId = "standards.IntuneTemplate.$($IntuneTemplate.TemplateList.value)" + $IntuneActions = if ($IntuneTemplate.action) { $IntuneTemplate.action } else { @() } + $IntuneReportingEnabled = ($IntuneActions | Where-Object { $_.value -and ($_.value.ToLower() -eq 'report' -or $_.value.ToLower() -eq 'remediate') }).Count -gt 0 + + [PSCustomObject]@{ + StandardId = $IntuneStandardId + ReportingEnabled = $IntuneReportingEnabled + } + } + } + } else { + [PSCustomObject]@{ + StandardId = $StandardId + ReportingEnabled = $ReportingEnabled + } + } + } + + $AllStandards = $StandardsData.StandardId + $ReportingEnabledStandards = ($StandardsData | Where-Object { $_.ReportingEnabled }).StandardId + $ReportingDisabledStandards = ($StandardsData | Where-Object { -not $_.ReportingEnabled }).StandardId + + foreach ($TenantName in $TenantStandards.Keys) { + if (-not $AppliestoAllTenants -and $TenantName -notin $TemplateAssignedTenants) { + continue + } + + $AllCount = $AllStandards.Count + $LatestDataCollection = $null + + $ComparisonTable = foreach ($StandardKey in $AllStandards) { + $IsReportingDisabled = $ReportingDisabledStandards -contains $StandardKey + + if ($TenantStandards[$TenantName].ContainsKey($StandardKey)) { + $StandardObject = $TenantStandards[$TenantName][$StandardKey] + $Value = $StandardObject.Value + + if ($StandardObject.LastRefresh) { + $RefreshTime = [DateTime]::Parse($StandardObject.LastRefresh) + if (-not $LatestDataCollection -or $RefreshTime -gt $LatestDataCollection) { + $LatestDataCollection = $RefreshTime + } + } + + $IsCompliant = ($Value -eq $true) + $IsLicenseMissing = ($Value -is [string] -and $Value -like 'License Missing:*') + + if ($IsReportingDisabled) { + $ComplianceStatus = 'Reporting Disabled' + } elseif ($IsCompliant) { + $ComplianceStatus = 'Compliant' + } elseif ($IsLicenseMissing) { + $ComplianceStatus = 'License Missing' + } else { + $ComplianceStatus = 'Non-Compliant' + } + + [PSCustomObject]@{ + StandardName = $StandardKey + Compliant = $IsCompliant + StandardValue = ($Value | ConvertTo-Json -Compress) + ComplianceStatus = $ComplianceStatus + ReportingDisabled = $IsReportingDisabled + } + } else { + if ($IsReportingDisabled) { + $ComplianceStatus = 'Reporting Disabled' + } else { + $ComplianceStatus = 'Non-Compliant' + } + + [PSCustomObject]@{ + StandardName = $StandardKey + Compliant = $false + StandardValue = 'NOT FOUND' + ComplianceStatus = $ComplianceStatus + ReportingDisabled = $IsReportingDisabled + } + } + } + + $CompliantStandards = ($ComparisonTable | Where-Object { $_.ComplianceStatus -eq 'Compliant' }).Count + $NonCompliantStandards = ($ComparisonTable | Where-Object { $_.ComplianceStatus -eq 'Non-Compliant' }).Count + $LicenseMissingStandards = ($ComparisonTable | Where-Object { $_.ComplianceStatus -eq 'License Missing' }).Count + $ReportingDisabledStandardsCount = ($ComparisonTable | Where-Object { $_.ReportingDisabled }).Count + + $AlignmentPercentage = if (($AllCount - $ReportingDisabledStandardsCount) -gt 0) { + [Math]::Round(($CompliantStandards / ($AllCount - $ReportingDisabledStandardsCount)) * 100) + } else { + 0 + } + + $LicenseMissingPercentage = if ($AllCount -gt 0) { + [Math]::Round(($LicenseMissingStandards / $AllCount) * 100) + } else { + 0 + } + + $Result = [PSCustomObject]@{ + TenantFilter = $TenantName + StandardName = $Template.templateName + StandardId = $Template.GUID + AlignmentScore = $AlignmentPercentage + LicenseMissingPercentage = $LicenseMissingPercentage + CombinedScore = $AlignmentPercentage + $LicenseMissingPercentage + CompliantStandards = $CompliantStandards + NonCompliantStandards = $NonCompliantStandards + LicenseMissingStandards = $LicenseMissingStandards + TotalStandards = $AllCount + ReportingDisabledCount = $ReportingDisabledStandardsCount + LatestDataCollection = if ($LatestDataCollection) { $LatestDataCollection } else { $null } + ComparisonDetails = $ComparisonTable + } + + $Results.Add($Result) + } + } + + return $Results + } catch { + Write-Error "Error getting tenant alignment data: $($_.Exception.Message)" + throw + } +} diff --git a/Modules/CIPPCore/Public/Functions/Get-TenantGroups.ps1 b/Modules/CIPPCore/Public/Functions/Get-TenantGroups.ps1 index ad4525a4d7de..761e1462d9cb 100644 --- a/Modules/CIPPCore/Public/Functions/Get-TenantGroups.ps1 +++ b/Modules/CIPPCore/Public/Functions/Get-TenantGroups.ps1 @@ -30,9 +30,9 @@ function Get-TenantGroups { } $Tenants = Get-Tenants @TenantParams - if ($GroupFilter) { - $Groups = Get-CIPPAzDataTableEntity @GroupTable -Filter "RowKey eq '$GroupFilter'" - $AllMembers = Get-CIPPAzDataTableEntity @MembersTable -Filter "GroupId eq '$GroupFilter'" + if ($GroupId) { + $Groups = Get-CIPPAzDataTableEntity @GroupTable -Filter "RowKey eq '$GroupId'" + $AllMembers = Get-CIPPAzDataTableEntity @MembersTable -Filter "GroupId eq '$GroupId'" } else { $Groups = Get-CIPPAzDataTableEntity @GroupTable $AllMembers = Get-CIPPAzDataTableEntity @MembersTable @@ -49,10 +49,10 @@ function Get-TenantGroups { $Group = $Groups | Where-Object { $_.RowKey -eq $Group.GroupId } if ($Group) { $Results.Add([PSCustomObject]@{ - Id = $Group.RowKey - Name = $Group.Name - Description = $Group.Description - }) + Id = $Group.RowKey + Name = $Group.Name + Description = $Group.Description + }) } } return $Results | Sort-Object Name @@ -66,10 +66,10 @@ function Get-TenantGroups { $Tenant = $Tenants | Where-Object { $Member.customerId -eq $_.customerId } if ($Tenant) { $MembersList.Add(@{ - customerId = $Tenant.customerId - displayName = $Tenant.displayName - defaultDomainName = $Tenant.defaultDomainName - }) + customerId = $Tenant.customerId + displayName = $Tenant.displayName + defaultDomainName = $Tenant.defaultDomainName + }) } } $SortedMembers = $MembersList | Sort-Object displayName @@ -77,11 +77,11 @@ function Get-TenantGroups { $SortedMembers = @() } $Results.Add([PSCustomObject]@{ - Id = $Group.RowKey - Name = $Group.Name - Description = $Group.Description - Members = @($SortedMembers) - }) + Id = $Group.RowKey + Name = $Group.Name + Description = $Group.Description + Members = @($SortedMembers) + }) } return $Results | Sort-Object Name } diff --git a/Modules/CIPPCore/Public/Functions/Test-CIPPStandardLicense.ps1 b/Modules/CIPPCore/Public/Functions/Test-CIPPStandardLicense.ps1 new file mode 100644 index 000000000000..68f434cbf5f3 --- /dev/null +++ b/Modules/CIPPCore/Public/Functions/Test-CIPPStandardLicense.ps1 @@ -0,0 +1,55 @@ +function Test-CIPPStandardLicense { + <# + .SYNOPSIS + Tests if a tenant has the required license capabilities for a specific standard + .DESCRIPTION + This function checks if a tenant has the necessary license capabilities to run a specific standard. + If the license is missing, it logs an error and sets the comparison field appropriately. + .PARAMETER StandardName + The name of the standard to check licensing for + .PARAMETER TenantFilter + The tenant to check licensing for + .PARAMETER RequiredCapabilities + Array of required capabilities for the standard + .FUNCTIONALITY + Internal + .EXAMPLE + Test-CIPPStandardLicense -StandardName "ConditionalAccessTemplate" -TenantFilter "contoso.onmicrosoft.com" -RequiredCapabilities @('AADPremiumService') + .EXAMPLE + Test-CIPPStandardLicense -StandardName "SafeLinksPolicy" -TenantFilter "contoso.onmicrosoft.com" -RequiredCapabilities @('DEFENDER_FOR_OFFICE_365_PLAN_1', 'DEFENDER_FOR_OFFICE_365_PLAN_2') + #> + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [string]$StandardName, + + [Parameter(Mandatory = $true)] + [string]$TenantFilter, + + [Parameter(Mandatory = $true)] + [string[]]$RequiredCapabilities + ) + + try { + $TenantCapabilities = Get-CIPPTenantCapabilities -TenantFilter $TenantFilter + + $Capabilities = foreach ($Capability in $RequiredCapabilities) { + Write-Host "Checking capability: $Capability" + if ($TenantCapabilities.$Capability -eq $true) { + $Capability + } + } + + if ($Capabilities.Count -le 0) { + Write-LogMessage -API 'Standards' -tenant $TenantFilter -message "Tenant does not have the required capability to run standard $StandardName`: The tenant needs one of the following service plans: $($RequiredCapabilities -join ',')" -sev Error + Set-CIPPStandardsCompareField -FieldName "standards.$StandardName" -FieldValue "License Missing: This tenant is not licensed for the following capabilities: $($RequiredCapabilities -join ',')" -Tenant $TenantFilter + Write-Host "Tenant does not have the required capability to run standard $StandardName - $($RequiredCapabilities -join ','). Exiting" + exit 0 + } + Write-Host "Tenant has the required capabilities for standard $StandardName" + } catch { + Write-LogMessage -API 'Standards' -tenant $TenantFilter -message "Error checking license capabilities for standard $StandardName`: $($_.Exception.Message)" -sev Error + Set-CIPPStandardsCompareField -FieldName "standards.$StandardName" -FieldValue "License Missing: Error checking license capabilities - $($_.Exception.Message)" -Tenant $TenantFilter + exit 0 + } +} diff --git a/Modules/CIPPCore/Public/Get-CIPPTenantCapabilities.ps1 b/Modules/CIPPCore/Public/Get-CIPPTenantCapabilities.ps1 index 5b44f04737e6..23c57432005a 100644 --- a/Modules/CIPPCore/Public/Get-CIPPTenantCapabilities.ps1 +++ b/Modules/CIPPCore/Public/Get-CIPPTenantCapabilities.ps1 @@ -7,12 +7,11 @@ function Get-CIPPTenantCapabilities { $Headers ) - $Org = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/organization' -tenantid $TenantFilter - $Plans = $Org.assignedPlans | Where-Object { $_.capabilityStatus -eq 'Enabled' } | Sort-Object -Property service -Unique | Select-Object capabilityStatus, service - + $Org = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/subscribedSkus' -tenantid $TenantFilter + $Plans = $Org.servicePlans | Where-Object { $_.provisioningStatus -eq 'Success' } | Sort-Object -Property serviceplanName -Unique | Select-Object servicePlanName, provisioningStatus $Results = @{} foreach ($Plan in $Plans) { - $Results."$($Plan.service)" = $Plan.capabilityStatus -eq 'Enabled' + $Results."$($Plan.servicePlanName)" = $Plan.provisioningStatus -eq 'Success' } [PSCustomObject]$Results } diff --git a/Modules/CIPPCore/Public/GraphHelper/New-GraphBulkRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-GraphBulkRequest.ps1 index de474b22f1f7..12b72accf29e 100644 --- a/Modules/CIPPCore/Public/GraphHelper/New-GraphBulkRequest.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/New-GraphBulkRequest.ps1 @@ -3,19 +3,21 @@ function New-GraphBulkRequest { .FUNCTIONALITY Internal #> - Param( + param( $tenantid, $NoAuthCheck, $scope, $asapp, $Requests, - $NoPaginateIds = @() + $NoPaginateIds = @(), + [ValidateSet('v1.0', 'beta')] + $Version = 'beta' ) if ($NoAuthCheck -or (Get-AuthorisedRequest -Uri $uri -TenantID $tenantid)) { $headers = Get-GraphToken -tenantid $tenantid -scope $scope -AsApp $asapp - $URL = 'https://graph.microsoft.com/beta/$batch' + $URL = "https://graph.microsoft.com/$Version/`$batch" # Track consecutive Graph API failures $TenantsTable = Get-CippTable -tablename Tenants diff --git a/Modules/CIPPCore/Public/GraphHelper/New-TeamsAPIGetRequest.ps1 b/Modules/CIPPCore/Public/GraphHelper/New-TeamsAPIGetRequest.ps1 index 8d3e99ce8892..9d97e7a01ab0 100644 --- a/Modules/CIPPCore/Public/GraphHelper/New-TeamsAPIGetRequest.ps1 +++ b/Modules/CIPPCore/Public/GraphHelper/New-TeamsAPIGetRequest.ps1 @@ -6,23 +6,49 @@ function New-TeamsAPIGetRequest($Uri, $tenantID, $Method = 'GET', $Resource = '4 if ((Get-AuthorisedRequest -Uri $uri -TenantID $tenantid)) { $token = Get-GraphToken -TenantID $tenantID -Scope "$Resource/.default" - $NextURL = $Uri $ReturnedData = do { + $handler = $null + $httpClient = $null + $response = $null try { - $Data = Invoke-RestMethod -ContentType "$ContentType;charset=UTF-8" -Uri $NextURL -Method $Method -Headers @{ - Authorization = $token.Authorization + # Create handler and client with compression disabled + $handler = New-Object System.Net.Http.HttpClientHandler + $handler.AutomaticDecompression = [System.Net.DecompressionMethods]::None + $httpClient = New-Object System.Net.Http.HttpClient($handler) + + # Add all required headers + $headers = @{ + 'Authorization' = $token.Authorization 'x-ms-client-request-id' = [guid]::NewGuid().ToString() 'x-ms-client-session-id' = [guid]::NewGuid().ToString() - 'x-ms-correlation-id' = [guid]::NewGuid() + 'x-ms-correlation-id' = [guid]::NewGuid().ToString() 'X-Requested-With' = 'XMLHttpRequest' 'x-ms-tnm-applicationid' = '045268c0-445e-4ac1-9157-d58f67b167d9' 'Accept' = 'application/json' + 'Accept-Encoding' = 'identity' + 'User-Agent' = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36' + } + + foreach ($header in $headers.GetEnumerator()) { + $httpClient.DefaultRequestHeaders.Add($header.Key, $header.Value) } + + $response = $httpClient.GetAsync($NextURL).Result + $contentString = $response.Content.ReadAsStringAsync().Result + + # Parse JSON and return data + $Data = $contentString | ConvertFrom-Json + $Data if ($noPagination) { $nextURL = $null } else { $nextURL = $data.NextLink } } catch { throw "Failed to make Teams API Get Request $_" + } finally { + # Proper cleanup in finally block to ensure disposal even on exceptions + if ($response) { $response.Dispose() } + if ($httpClient) { $httpClient.Dispose() } + if ($handler) { $handler.Dispose() } } } until ($null -eq $NextURL) return $ReturnedData diff --git a/Modules/CIPPCore/Public/New-CIPPBackup.ps1 b/Modules/CIPPCore/Public/New-CIPPBackup.ps1 index ba9194085e0e..024ba4571721 100644 --- a/Modules/CIPPCore/Public/New-CIPPBackup.ps1 +++ b/Modules/CIPPCore/Public/New-CIPPBackup.ps1 @@ -89,7 +89,7 @@ function New-CIPPBackup { try { $null = Add-CIPPAzDataTableEntity @Table -entity $entity -Force Write-LogMessage -headers $Headers -API $APINAME -message 'Created backup' -Sev 'Debug' - $State = 'Backup finished succesfully' + $State = 'Backup finished successfully' } catch { $State = 'Failed to write backup to table storage' $ErrorMessage = Get-CippException -Exception $_ @@ -99,10 +99,9 @@ function New-CIPPBackup { } } - return [pscustomobject]@{ - BackupName = $RowKey - BackupState = $State - BackupData = $BackupData - } + return @([pscustomobject]@{ + BackupName = $RowKey + BackupState = $State + }) } diff --git a/Modules/CIPPCore/Public/New-CIPPBackupTask.ps1 b/Modules/CIPPCore/Public/New-CIPPBackupTask.ps1 index 05f2b0added7..1814abc23fe0 100644 --- a/Modules/CIPPCore/Public/New-CIPPBackupTask.ps1 +++ b/Modules/CIPPCore/Public/New-CIPPBackupTask.ps1 @@ -45,7 +45,7 @@ function New-CIPPBackupTask { 'https://graph.microsoft.com/beta/deviceManagement/windowsQualityUpdateProfiles' ) - $Policies = foreach ($url in $GraphURLS) { + foreach ($url in $GraphURLS) { try { $Policies = New-GraphGetRequest -uri "$($url)" -tenantid $TenantFilter $URLName = (($url).split('?') | Select-Object -First 1) -replace 'https://graph.microsoft.com/beta/deviceManagement/', '' diff --git a/Modules/CIPPCore/Public/New-CIPPCAPolicy.ps1 b/Modules/CIPPCore/Public/New-CIPPCAPolicy.ps1 index 8dd288691767..a6c6ede0714d 100644 --- a/Modules/CIPPCore/Public/New-CIPPCAPolicy.ps1 +++ b/Modules/CIPPCore/Public/New-CIPPCAPolicy.ps1 @@ -7,6 +7,7 @@ function New-CIPPCAPolicy { $State, $Overwrite, $ReplacePattern = 'none', + $DisableSD = $false, $APIName = 'Create CA Policy', $Headers ) @@ -225,7 +226,13 @@ function New-CIPPCAPolicy { } } } - + if ($DisableSD -eq $true) { + #Send request to disable security defaults. + $body = '{ "isEnabled": false }' + $null = New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/policies/identitySecurityDefaultsEnforcementPolicy' -Type patch -Body $body -ContentType 'application/json' + Write-LogMessage -Headers $User -API $APINAME -tenant $($Tenant) -message "Disabled Security Defaults for tenant $($TenantFilter)" -Sev 'Info' + Start-Sleep 3 + } $RawJSON = ConvertTo-Json -InputObject $JSONObj -Depth 10 -Compress Write-Information $RawJSON try { diff --git a/Modules/CIPPCore/Public/New-CIPPIntuneTemplate.ps1 b/Modules/CIPPCore/Public/New-CIPPIntuneTemplate.ps1 index 452e81574db6..963b370668ef 100644 --- a/Modules/CIPPCore/Public/New-CIPPIntuneTemplate.ps1 +++ b/Modules/CIPPCore/Public/New-CIPPIntuneTemplate.ps1 @@ -7,7 +7,6 @@ function New-CIPPIntuneTemplate { $CIPPURL, $ODataType ) - Write-Host "These are all bound params: $urlname, $id, $TenantFilter, $ActionResults, $CIPPURL, $ODataType" if ($ODataType) { switch -wildcard ($ODataType) { '*CompliancePolicy' { diff --git a/Modules/CIPPCore/Public/New-CIPPSharepointSite.ps1 b/Modules/CIPPCore/Public/New-CIPPSharepointSite.ps1 index cc5f7a3a1203..09ac3a485e20 100644 --- a/Modules/CIPPCore/Public/New-CIPPSharepointSite.ps1 +++ b/Modules/CIPPCore/Public/New-CIPPSharepointSite.ps1 @@ -32,7 +32,7 @@ function New-CIPPSharepointSite { #> [CmdletBinding(SupportsShouldProcess = $true)] - Param( + param( [Parameter(Mandatory = $true)] [string]$SiteName, @@ -139,7 +139,14 @@ function New-CIPPSharepointSite { 'accept' = 'application/json;odata.metadata=none' 'odata-version' = '4.0' } - $Results = New-GraphPostRequest -scope "$($SharePointInfo.AdminUrl)/.default" -uri "$($SharePointInfo.AdminUrl)/_api/SPSiteManager/create" -Body ($body | ConvertTo-Json -Compress -Depth 10) -tenantid $TenantFilter -ContentType 'application/json' -AddedHeaders $AddedHeaders + try { + $Results = New-GraphPOSTRequest -scope "$($SharePointInfo.AdminUrl)/.default" -uri "$($SharePointInfo.AdminUrl)/_api/SPSiteManager/create" -body (ConvertTo-Json -Depth 10 -InputObject $body) -tenantid $TenantFilter -AddedHeaders $AddedHeaders + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Result = "Failed to create new SharePoint site $SiteName with URL $SiteUrl. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -sev Error -LogData $ErrorMessage + throw $Result + } } # Check the results. This response is weird. https://learn.microsoft.com/en-us/sharepoint/dev/apis/site-creation-rest @@ -147,29 +154,29 @@ function New-CIPPSharepointSite { '0' { $Result = "Failed to create new SharePoint site $SiteName with URL $SiteUrl. The site doesn't exist." Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -sev Error - throw $Results + throw $Result } '1' { $Result = "Successfully created new SharePoint site $SiteName with URL $SiteUrl. The site is however currently being provisioned. Please wait for it to finish." Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -sev Info - return $Results + return $Result } '2' { $Result = "Successfully created new SharePoint site $SiteName with URL $SiteUrl" Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -sev Info - return $Results + return $Result } '3' { $Result = "Failed to create new SharePoint site $SiteName with URL $SiteUrl. An error occurred while provisioning the site." Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -sev Error - throw $Results + throw $Result } '4' { Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Result -sev Error $Result = "Failed to create new SharePoint site $SiteName with URL $SiteUrl. The site already exists." throw $Result } - Default {} + default {} } diff --git a/Modules/CIPPCore/Public/Remove-CIPPCalendarInvites.ps1 b/Modules/CIPPCore/Public/Remove-CIPPCalendarInvites.ps1 index 0fa8eab58997..4c2919398974 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPCalendarInvites.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPCalendarInvites.ps1 @@ -1,22 +1,23 @@ function Remove-CIPPCalendarInvites { [CmdletBinding()] param( - $userid, - $tenantFilter, - $username, + $UserID, + $TenantFilter, + $Username, $APIName = 'Remove Calendar Invites', $Headers ) try { - - New-ExoRequest -tenantid $tenantFilter -cmdlet 'Remove-CalendarEvents' -Anchor $username -cmdParams @{Identity = $username; QueryWindowInDays = 730 ; CancelOrganizedMeetings = $true ; Confirm = $false } - Write-LogMessage -headers $Headers -API $APIName -message "Cancelled all calendar invites for $($username)" -Sev 'Info' -tenant $tenantFilter - "Cancelled all calendar invites for $($username)" + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Remove-CalendarEvents' -Anchor $Username -cmdParams @{Identity = $Username; QueryWindowInDays = 730 ; CancelOrganizedMeetings = $true ; Confirm = $false } + $Result = "Successfully cancelled all calendar invites for $($Username)" + Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Info' -tenant $TenantFilter + return $Result } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers -API $APIName -message "Could not cancel calendar invites for $($username): $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $tenantFilter -LogData $ErrorMessage - return "Could not cancel calendar invites for $($username). Error: $($ErrorMessage.NormalizedError)" + $Result = "Failed to cancel calendar invites for $($Username). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + throw $Result } } diff --git a/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 b/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 index 933f6fbdb99e..1284db3c752d 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 @@ -2,50 +2,50 @@ function Remove-CIPPGroups { [CmdletBinding()] param( $Username, - $tenantFilter, + $TenantFilter, $APIName = 'Remove From Groups', $Headers, - $userid + $UserID ) if (-not $userid) { - $userid = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($Username)" -tenantid $Tenantfilter).id + $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,assignedLicenses&`$top=999" -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 { + $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' Import-Module '.\Modules\CIPPCore' - $group = $_ + $Group = $_ try { - $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 + $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 ($IsLicensed) { - "Could not remove $($using:Username) from $Groupname. This is because the group has licenses assigned to it." + "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 + $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 + $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 } + $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 - "Could not remove $($using:Username) from group $($Groupname): $($ErrorMessage.NormalizedError). This is likely because its a Dynamic Group or synched with active directory" + 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 + "Could not remove $($using:Username) from group $($GroupName): $($ErrorMessage.NormalizedError). This is likely because its a Dynamic Group or synched with active directory" } } - if (!$Returnval) { + if (-not $Returnval) { $Returnval = "$($Username) is not a member of any groups." Write-LogMessage -headers $Headers -API $APIName -message "$($Username) is not a member of any groups" -Sev 'Info' -tenant $TenantFilter } diff --git a/Modules/CIPPCore/Public/Remove-CIPPMailboxRule.ps1 b/Modules/CIPPCore/Public/Remove-CIPPMailboxRule.ps1 index aeb62aad3446..579c7f2d4801 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPMailboxRule.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPMailboxRule.ps1 @@ -18,30 +18,35 @@ function Remove-CIPPMailboxRule { $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" + $Message = "No rules found for $($Username) to delete" + Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Info' -tenant $TenantFilter + return $Message } else { ForEach ($rule in $Rules) { $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Remove-InboxRule' -Anchor $Username -cmdParams @{Identity = $rule.Identity } } + $Message = "Successfully deleted all rules for $($Username)" Write-LogMessage -headers $Headers -API $APIName -message "Deleted rules for $($Username)" -Sev 'Info' -tenant $TenantFilter - return "Deleted rules for $($Username)" + return $Message } } 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)" + $Message = "Failed to delete rules for $($Username). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + throw $Message } } else { # Only delete 1 rule try { $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Remove-InboxRule' -Anchor $Username -cmdParams @{Identity = $RuleId } + $Message = "Successfully deleted mailbox rule $($RuleName) for $($Username)" Write-LogMessage -headers $Headers -API $APIName -message "Deleted mailbox rule $($RuleName) for $($Username)" -Sev 'Info' -tenant $TenantFilter - return "Deleted mailbox rule $($RuleName) for $($Username)" + return $Message } 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)" + $Message = "Failed to delete rule for $($Username). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + throw $Message } } } diff --git a/Modules/CIPPCore/Public/Remove-CIPPMobileDevice.ps1 b/Modules/CIPPCore/Public/Remove-CIPPMobileDevice.ps1 index d1d0a8cb45ba..e436fce09d5c 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPMobileDevice.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPMobileDevice.ps1 @@ -1,28 +1,37 @@ function Remove-CIPPMobileDevice { [CmdletBinding()] param( - $userid, - $tenantFilter, - $username, + $UserId, + $TenantFilter, + $Username, $APIName = 'Remove Mobile', $Headers ) try { - $devices = New-ExoRequest -tenantid $tenantFilter -cmdlet 'Get-MobileDevice' -Anchor $username -cmdParams @{mailbox = $username } | ForEach-Object { + $RemovedDevices = [System.Collections.Generic.List[string]]::new() + $ErrorDevices = [System.Collections.Generic.List[string]]::new() + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-MobileDevice' -Anchor $Username -cmdParams @{mailbox = $Username } | ForEach-Object { try { - New-ExoRequest -tenantid $tenantFilter -cmdlet 'Remove-MobileDevice' -Anchor $username -cmdParams @{Identity = $_.Identity } - "Removed device: $($_.FriendlyName)" + $MobileDevice = $_ + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Remove-MobileDevice' -Anchor $Username -cmdParams @{Identity = $MobileDevice.Identity } + $RemovedDevices.Add("$($MobileDevice.FriendlyName)") } catch { - "Could not remove device: $($_.FriendlyName)" + $ErrorDevices.Add("$($MobileDevice.FriendlyName)") } } - if (!$Devices) { $Devices = 'No mobile devices have been removed as we could not find any' } - Write-LogMessage -headers $Headers -API $APIName -message "Deleted mobile devices for $($username)" -Sev 'Info' -tenant $tenantFilter - return $devices + if ($ErrorDevices.Count -eq 0) { + $Message = "Successfully removed $($RemovedDevices.Count) mobile devices for $($Username): $($RemovedDevices -join '; ')" + } else { + $Message = "Failed to remove all mobile devices for $($Username). Successfully removed $($RemovedDevices.Count) mobile devices: $($RemovedDevices -join '; '). Failed to remove $($ErrorDevices.Count) mobile devices: $($ErrorDevices -join '; ')" + Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Error' -tenant $TenantFilter + } + return $Message } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers -API $APIName -message "Could not delete mobile devices for $($username): $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $tenantFilter -LogData $ErrorMessage - return "Could not delete mobile devices for $($username). Error: $($ErrorMessage.NormalizedError)" + $Message = "Failed to remove mobile devices for $($Username). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + throw $Message } } + diff --git a/Modules/CIPPCore/Public/Remove-CIPPUser.ps1 b/Modules/CIPPCore/Public/Remove-CIPPUser.ps1 index d892e9421227..92b9ae2c7529 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPUser.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPUser.ps1 @@ -2,22 +2,28 @@ function Remove-CIPPUser { [CmdletBinding()] param ( $Headers, - $userid, - $username, + [parameter(Mandatory = $true)] + [string]$UserID, + [string]$Username, $APIName = 'Remove User', $TenantFilter ) + + try { - $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($userid)" -type DELETE -tenant $TenantFilter - Write-LogMessage -headers $Headers -API $APIName -message "Deleted account $username" -Sev 'Info' -tenant $TenantFilter - return "Deleted the user account $username" + $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($UserID)" -type DELETE -tenant $TenantFilter + $Result = "Successfully deleted user with ID: '$UserID'" + if (-not [string]::IsNullOrEmpty($Username)) { $Result += " and Username: '$Username'" } + Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Info' -tenant $TenantFilter + return $Result } catch { $ErrorMessage = Get-CippException -Exception $_ - $Message = "Could not delete $username. Error: $($ErrorMessage.NormalizedError)" - Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - return $Message + $Result = "Failed to delete user with ID: '$UserID'. Error: $($ErrorMessage.NormalizedError)" + if (-not [string]::IsNullOrEmpty($Username)) { $Result += " and Username: '$Username'" } + Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + throw $Result } } diff --git a/Modules/CIPPCore/Public/Remove-CIPPUserMFA.ps1 b/Modules/CIPPCore/Public/Remove-CIPPUserMFA.ps1 index 2d9efd1e30e2..722d0b73a616 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPUserMFA.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPUserMFA.ps1 @@ -23,16 +23,21 @@ function Remove-CIPPUserMFA { [Parameter(Mandatory = $true)] [string]$TenantFilter, [Parameter(Mandatory = $false)] - $Headers + $Headers, + [Parameter(Mandatory = $false)] + $APIName = 'Remove MFA Methods' ) Write-Information "Getting auth methods for $UserPrincipalName" try { $AuthMethods = New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/users/$UserPrincipalName/authentication/methods" -tenantid $TenantFilter -AsApp $true } catch { - Write-LogMessage -headers $Headers -API 'Remove-CIPPUserMFA' -tenant $TenantFilter -message "Failed to get MFA methods for user $UserPrincipalName" -sev 'Error' -LogData (Get-CippException -Exception $_) - return "Failed to get MFA methods for user $UserPrincipalName - $($_.Exception.Message)" + $ErrorMessage = Get-CippException -Exception $_ + $Message = "Failed to get MFA methods for user $UserPrincipalName. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Message -sev 'Error' -LogData $ErrorMessage + throw $Message } + $Requests = [System.Collections.Generic.List[object]]::new() foreach ($Method in $AuthMethods) { if ($Method.'@odata.type' -and $Method.'@odata.type' -ne '#microsoft.graph.passwordAuthenticationMethod') { @@ -44,22 +49,31 @@ function Remove-CIPPUserMFA { }) } } + if (($Requests | Measure-Object).Count -eq 0) { - Write-LogMessage -headers $Headers -API 'Remove-CIPPUserMFA' -tenant $TenantFilter -message "No MFA methods found for user $UserPrincipalName" -sev 'Info' - $Results = "No MFA methods found for user $($UserPrincipalName)" + $Results = "No MFA methods found for user $UserPrincipalName" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Results -sev 'Info' + return $Results } else { if ($PSCmdlet.ShouldProcess("Remove MFA methods for $UserPrincipalName")) { - $Results = New-GraphBulkRequest -Requests $Requests -tenantid $TenantFilter -asapp $true -erroraction stop - if ($Results.status -eq 204) { - Write-LogMessage -headers $Headers -API 'Remove-CIPPUserMFA' -tenant $TenantFilter -message "Successfully removed MFA methods for user $UserPrincipalName" -sev 'Info' - $Results = [pscustomobject]@{'Results' = "Successfully completed request. User $($Request.Query.ID) must supply MFA at next logon" } - } else { - $FailedAuthMethods = (($Results | Where-Object { $_.status -ne 204 }).id -split '-')[0] -join ', ' - Write-LogMessage -headers $Headers -API 'Remove-CIPPUserMFA' -tenant $TenantFilter -message "Failed to remove MFA methods for $FailedAuthMethods" -sev 'Error' - $Results = "Failed to reset MFA methods for $FailedAuthMethods" + try { + $Results = New-GraphBulkRequest -Requests $Requests -tenantid $TenantFilter -asapp $true -ErrorAction Stop + if ($Results.status -eq 204) { + $Message = "Successfully removed MFA methods for user $UserPrincipalName. User must supply MFA at next logon" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Message -sev 'Info' + return $Message + } else { + $FailedAuthMethods = (($Results | Where-Object { $_.status -ne 204 }).id -split '-')[0] -join ', ' + $Message = "Failed to remove MFA methods for $FailedAuthMethods on user $UserPrincipalName" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Message -sev 'Error' + throw $Message + } + } catch { + $ErrorMessage = Get-CippException -Exception $_ + $Message = "Failed to remove MFA methods for user $UserPrincipalName. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -tenant $TenantFilter -message $Message -sev 'Error' -LogData $ErrorMessage + throw $Message } } } - - return $Results } diff --git a/Modules/CIPPCore/Public/Revoke-CIPPSessions.ps1 b/Modules/CIPPCore/Public/Revoke-CIPPSessions.ps1 index e9d319008a2d..2718233be838 100644 --- a/Modules/CIPPCore/Public/Revoke-CIPPSessions.ps1 +++ b/Modules/CIPPCore/Public/Revoke-CIPPSessions.ps1 @@ -9,15 +9,15 @@ function Revoke-CIPPSessions { ) try { - $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($userid)/invalidateAllRefreshTokens" -tenantid $TenantFilter -type POST -body '{}' -verbose - Write-LogMessage -headers $Headers -API $APIName -message "Revoked sessions for $($username)" -Sev 'Info' -tenant $TenantFilter - return "Success. All sessions by $username have been revoked" + $null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($UserID)/invalidateAllRefreshTokens" -tenantid $TenantFilter -type POST -body '{}' -verbose + $Result = "Successfully revoked sessions for $($Username)" + Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Info' -tenant $TenantFilter + return $Result } catch { $ErrorMessage = Get-CippException -Exception $_ - $Result = "Failed to revoke sessions for $($username). Error: $($ErrorMessage.NormalizedError)" + $Result = "Failed to revoke sessions for $($Username). Error: $($ErrorMessage.NormalizedError)" Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - # TODO - needs to be changed to throw, but the rest of the functions using this cant handle anything but a return. - return $Result + throw $Result } } diff --git a/Modules/CIPPCore/Public/Set-CIPPCAExclusion.ps1 b/Modules/CIPPCore/Public/Set-CIPPCAExclusion.ps1 index ea3ad84de6a5..41e7b560e982 100644 --- a/Modules/CIPPCore/Public/Set-CIPPCAExclusion.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPCAExclusion.ps1 @@ -6,39 +6,78 @@ function Set-CIPPCAExclusion { $UserID, $PolicyId, $Username, + $Users, $Headers ) try { - $CheckExististing = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/identity/conditionalAccess/policies/$($PolicyId)" -tenantid $TenantFilter -AsApp $true + $CheckExisting = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/identity/conditionalAccess/policies/$($PolicyId)" -tenantid $TenantFilter -AsApp $true if ($ExclusionType -eq 'add') { - $NewExclusions = [pscustomobject]@{ - conditions = [pscustomobject]@{ users = [pscustomobject]@{ - excludeUsers = @($CheckExististing.conditions.users.excludeUsers + $UserID) + if ($Users) { + $Username = $Users.addedFields.userPrincipalName + $ExcludeUsers = [System.Collections.Generic.List[string]]::new() + foreach ($User in $CheckExisting.conditions.users.excludeUsers) { + $ExcludeUsers.Add($User) + } + foreach ($User in $Users.value) { + if ($ExcludeUsers -notcontains $User) { + $ExcludeUsers.Add($User) + } + } + $NewExclusions = [pscustomobject]@{ + conditions = [pscustomobject]@{ users = [pscustomobject]@{ + excludeUsers = $ExcludeUsers + } + } + } + } else { + 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 + } + $NewExclusions = [pscustomobject]@{ + conditions = [pscustomobject]@{ users = [pscustomobject]@{ + excludeUsers = @($CheckExisting.conditions.users.excludeUsers + $UserID) + } } } } + $RawJson = ConvertTo-Json -Depth 10 -InputObject $NewExclusions if ($PSCmdlet.ShouldProcess($PolicyId, "Add exclusion for $UserID")) { - New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/identity/conditionalAccess/policies/$($CheckExististing.id)" -tenantid $tenantfilter -type PATCH -body $RawJSON -AsApp $true + New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/identity/conditionalAccess/policies/$($CheckExisting.id)" -tenantid $tenantfilter -type PATCH -body $RawJSON -AsApp $true } } if ($ExclusionType -eq 'remove') { + if ($Users) { + $UserID = $Users.value + $Username = $Users.addedFields.userPrincipalName + } else { + 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 + } + $UserID = @($UserID) + } $NewExclusions = [pscustomobject]@{ conditions = [pscustomobject]@{ users = [pscustomobject]@{ - excludeUsers = @($CheckExististing.conditions.users.excludeUsers | Where-Object { $_ -ne $UserID }) + excludeUsers = @($CheckExisting.conditions.users.excludeUsers | Where-Object { $UserID -notcontains $_ }) } } } $RawJson = ConvertTo-Json -Depth 10 -InputObject $NewExclusions if ($PSCmdlet.ShouldProcess($PolicyId, "Remove exclusion for $UserID")) { - New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/identity/conditionalAccess/policies/$($CheckExististing.id)" -tenantid $tenantfilter -type PATCH -body $RawJSON -AsApp $true + New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/identity/conditionalAccess/policies/$($CheckExisting.id)" -tenantid $tenantfilter -type PATCH -body $RawJSON -AsApp $true } } - "Successfully performed $($ExclusionType) exclusion for $username from policy $($PolicyId)" - Write-LogMessage -headers $Headers -API 'Set-CIPPConditionalAccessExclusion' -message "Successfully performed $($ExclusionType) exclusion for $username from policy $($PolicyId)" -Sev 'Info' -tenant $TenantFilter + + foreach ($User in $Username) { + "Successfully performed $($ExclusionType) exclusion for $User from policy $($CheckExisting.displayName)" + Write-LogMessage -headers $Headers -API 'Set-CIPPCAExclusion' -message "Successfully performed $($ExclusionType) exclusion for $User from policy $($CheckExisting.displayName)" -Sev 'Info' -tenant $TenantFilter + } } catch { - "Failed to $($ExclusionType) user exclusion for $username from policy $($PolicyId): $($_.Exception.Message)" - Write-LogMessage -headers $Headers -API 'Set-CIPPConditionalAccessExclusion' -message "Failed to $($ExclusionType) user exclusion for $username from policy $($PolicyId): $_" -Sev 'Error' -tenant $TenantFilter -LogData (Get-CippException -Exception $_) + foreach ($User in $Username) { + "Failed to $($ExclusionType) user exclusion for $User from policy $($CheckExisting.displayName): $($_.Exception.Message)" + Write-LogMessage -headers $Headers -API 'Set-CIPPCAExclusion' -message "Failed to $($ExclusionType) user exclusion for $User from policy $($CheckExisting.displayName): $_" -Sev 'Error' -tenant $TenantFilter -LogData (Get-CippException -Exception $_) + } } } + diff --git a/Modules/CIPPCore/Public/Set-CIPPCAPolicyServiceException.ps1 b/Modules/CIPPCore/Public/Set-CIPPCAPolicyServiceException.ps1 new file mode 100644 index 000000000000..8b52c1d83d6f --- /dev/null +++ b/Modules/CIPPCore/Public/Set-CIPPCAPolicyServiceException.ps1 @@ -0,0 +1,82 @@ +function Set-CIPPCAPolicyServiceException { + [CmdletBinding(SupportsShouldProcess = $true)] + param( + $TenantFilter, + $PolicyId + ) + + $CSPtenantId = $env:TenantID + + # Get the current policy + $policy = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/identity/conditionalAccess/policies/$($PolicyId)" -tenantid $TenantFilter -AsApp $true + + # If the policy is set to affect either all or all guests/external users + if ($policy.conditions.users.includeUsers -eq "All" -OR $policy.conditions.users.includeGuestsOrExternalUsers.externalTenants.membershipKind -eq "all") { + + # Check if the policy already has the correct service provider exception + if ($policy.conditions.users.excludeGuestsOrExternalUsers) { + $excludeConfig = $policy.conditions.users.excludeGuestsOrExternalUsers + + # Check if serviceProvider is already in guestOrExternalUserTypes + $hasServiceProvider = $excludeConfig.guestOrExternalUserTypes -match "serviceProvider" + + # Check if externalTenants is properly configured + if ($excludeConfig.externalTenants) { + $externalTenants = $excludeConfig.externalTenants + $hasCorrectExternalTenants = ($externalTenants.membershipKind -eq "enumerated" -and + $externalTenants.members -contains $CSPtenantId) + + # If already configured, exit without making changes + if ($hasServiceProvider -and $hasCorrectExternalTenants) { + return "Policy $PolicyId already has the correct service provider configuration. No changes needed." + } + } + } + + # If excludeGuestsOrExternalUsers is empty, add the entire exclusion + if (!($policy.conditions.users.excludeGuestsOrExternalUsers)) { + + # Define data + $excludeServiceProviderData = [pscustomobject]@{ + guestOrExternalUserTypes = "serviceProvider" + externalTenants = [pscustomobject]@{ + '@odata.type' = "#microsoft.graph.conditionalAccessEnumeratedExternalTenants" + membershipKind = "enumerated" + members = @( + $CSPtenantId + ) + } + } + + # Add data to cached policy + $policy.conditions.users.excludeGuestsOrExternalUsers = $excludeServiceProviderData + } + + # If excludeGuestsOrExternalUsers already has content correct it to match $excludeServiceProviderData + if ($policy.conditions.users.excludeGuestsOrExternalUsers) { + + # If guestOrExternalUserTypes doesn't include type serviceProvider add it + if ($policy.conditions.users.excludeGuestsOrExternalUsers.guestOrExternalUserTypes -notmatch "serviceProvider") { + $policy.conditions.users.excludeGuestsOrExternalUsers.guestOrExternalUserTypes += ",serviceProvider" + } + + # If guestOrExternalUserTypes includes type serviceProvider and membershipKind is not all tenants + if ($policy.conditions.users.excludeGuestsOrExternalUsers.guestOrExternalUserTypes -match "serviceProvider" -AND $policy.conditions.users.excludeGuestsOrExternalUsers.externalTenants.membershipKind -ne "all") { + + # If membershipKind is enumerated and members does not include our tenant add it + if ($policy.conditions.users.excludeGuestsOrExternalUsers.externalTenants.membershipKind -eq "enumerated" -AND $policy.conditions.users.excludeGuestsOrExternalUsers.externalTenants.members -notmatch $CSPtenantId) { + $policy.conditions.users.excludeGuestsOrExternalUsers.externalTenants.members += $($CSPtenantId) + } + } + } + + } + + # Patch policy with updated data. + # TemplateId,createdDateTime,modifiedDateTime can't be written back so exclude them using -ExcludeProperty + if ($PSCmdlet.ShouldProcess($PolicyId, "Update policy with service provider exception")) { + $patch = New-GraphPOSTRequest -uri "https://graph.microsoft.com/beta/identity/conditionalAccess/policies/$($policy.id)" -tenantid $TenantFilter -type PATCH -body ($policy | Select-Object * -ExcludeProperty TemplateId,createdDateTime,modifiedDateTime | ConvertTo-Json -Depth 20) -AsApp $true + return "Successfully added service provider to policy $PolicyId" + } + +} diff --git a/Modules/CIPPCore/Public/Set-CIPPForwarding.ps1 b/Modules/CIPPCore/Public/Set-CIPPForwarding.ps1 index 81e8cf53c9fe..2db867e16b51 100644 --- a/Modules/CIPPCore/Public/Set-CIPPForwarding.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPForwarding.ps1 @@ -36,10 +36,10 @@ function Set-CIPPForwarding { #> [CmdletBinding(SupportsShouldProcess = $true)] param( - [string]$userid, - [string]$forwardingSMTPAddress, - [string]$tenantFilter, - [string]$username, + [string]$UserID, + [string]$ForwardingSMTPAddress, + [string]$TenantFilter, + [string]$Username, $Headers, [string]$APIName = 'Forwarding', [string]$Forward, @@ -49,25 +49,26 @@ function Set-CIPPForwarding { try { - if (!$username) { $username = $userid } - if ($PSCmdlet.ShouldProcess($username, 'Set forwarding')) { + if (!$Username) { $Username = $UserID } + if ($PSCmdlet.ShouldProcess($Username, 'Set forwarding')) { if ($Disable -eq $true) { - Write-Output "Disabling forwarding for $username" - $null = New-ExoRequest -tenantid $tenantFilter -cmdlet 'Set-mailbox' -cmdParams @{Identity = $userid; ForwardingSMTPAddress = $null; ForwardingAddress = $null ; DeliverToMailboxAndForward = $false } -Anchor $username - $Message = "Disabled forwarding for $username" + Write-Output "Disabling forwarding for $Username" + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Set-Mailbox' -cmdParams @{Identity = $UserID; ForwardingSMTPAddress = $null; ForwardingAddress = $null ; DeliverToMailboxAndForward = $false } -Anchor $Username + $Message = "Successfully disabled forwarding for $Username" } elseif ($Forward) { - $null = New-ExoRequest -tenantid $tenantFilter -cmdlet 'Set-mailbox' -cmdParams @{Identity = $userid; ForwardingSMTPAddress = $null; ForwardingAddress = $Forward ; DeliverToMailboxAndForward = $KeepCopy } -Anchor $username - $Message = "Forwarding all email for $username to Internal Address $Forward and keeping a copy set to $KeepCopy" + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Set-Mailbox' -cmdParams @{Identity = $UserID; ForwardingSMTPAddress = $null; ForwardingAddress = $Forward ; DeliverToMailboxAndForward = $KeepCopy } -Anchor $Username + $Message = "Successfully set forwarding for $Username to Internal Address $Forward with keeping a copy set to $KeepCopy" } elseif ($forwardingSMTPAddress) { - $null = New-ExoRequest -tenantid $tenantFilter -cmdlet 'Set-mailbox' -cmdParams @{Identity = $userid; ForwardingSMTPAddress = $forwardingSMTPAddress; ForwardingAddress = $null ; DeliverToMailboxAndForward = $KeepCopy } -Anchor $username - $Message = "Forwarding all email for $username to External Address $ForwardingSMTPAddress and keeping a copy set to $KeepCopy" + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Set-Mailbox' -cmdParams @{Identity = $UserID; ForwardingSMTPAddress = $ForwardingSMTPAddress; ForwardingAddress = $null ; DeliverToMailboxAndForward = $KeepCopy } -Anchor $Username + $Message = "Successfully set forwarding for $Username to External Address $ForwardingSMTPAddress with keeping a copy set to $KeepCopy" } } Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Info' -tenant $TenantFilter return $Message } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers -API $APIName -message "Could not add forwarding for $($username). Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - return "Could not add forwarding for $($username). Error: $($ErrorMessage.NormalizedError)" + $Message = "Failed to set forwarding for $($Username). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + throw $Message } } diff --git a/Modules/CIPPCore/Public/Set-CIPPHideFromGAL.ps1 b/Modules/CIPPCore/Public/Set-CIPPHideFromGAL.ps1 index 23d8bc8e8462..0c87d039ae71 100644 --- a/Modules/CIPPCore/Public/Set-CIPPHideFromGAL.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPHideFromGAL.ps1 @@ -15,8 +15,8 @@ function Set-CIPPHideFromGAL { return $Result } catch { $ErrorMessage = Get-CippException -Exception $_ - $Result = "Failed to hide $($UserId) from GAL. Error: $($ErrorMessage.NormalizedError)" - Write-LogMessage -headers $Headers -API $APIName -message $Result -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - return $Result + $Message = "Failed to set $($UserId) to $Text in GAL. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + throw $Message } } diff --git a/Modules/CIPPCore/Public/Set-CIPPMailboxAccess.ps1 b/Modules/CIPPCore/Public/Set-CIPPMailboxAccess.ps1 index 7ac44a00b9ee..c4ab09866086 100644 --- a/Modules/CIPPCore/Public/Set-CIPPMailboxAccess.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPMailboxAccess.ps1 @@ -11,18 +11,15 @@ function Set-CIPPMailboxAccess { ) try { - $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Add-MailboxPermission' -cmdParams @{Identity = $userid; user = $AccessUser; automapping = $Automap; accessRights = $AccessRights; InheritanceType = 'all' } -Anchor $userid + $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Add-MailboxPermission' -cmdParams @{Identity = $userid; user = $AccessUser; AutoMapping = $Automap; accessRights = $AccessRights; InheritanceType = 'all' } -Anchor $userid - if ($Automap) { - Write-LogMessage -headers $Headers -API $APIName -message "Gave $AccessRights permissions to $($AccessUser) on $($userid) with automapping" -Sev 'Info' -tenant $TenantFilter - return "Added $($AccessUser) to $($userid) Shared Mailbox with automapping, with the following permissions: $AccessRights" - } else { - Write-LogMessage -headers $Headers -API $APIName -message "Gave $AccessRights permissions to $($AccessUser) on $($userid) without automapping" -Sev 'Info' -tenant $TenantFilter - return "Added $($AccessUser) to $($userid) Shared Mailbox without automapping, with the following permissions: $AccessRights" - } + $Message = "Successfully added $($AccessUser) to $($userid) Shared Mailbox $($Automap ? 'with' : 'without') AutoMapping, with the following permissions: $AccessRights" + Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Info' -tenant $TenantFilter + return $Message } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers -API $APIName -message "Could not add mailbox permissions for $($AccessUser) on $($userid). Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - return "Could not add shared mailbox permissions for $($userid). Error: $($ErrorMessage.NormalizedError)" + $Message = "Failed to add mailbox permissions for $($AccessUser) on $($userid). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + throw $Message } } diff --git a/Modules/CIPPCore/Public/Set-CIPPMailboxType.ps1 b/Modules/CIPPCore/Public/Set-CIPPMailboxType.ps1 index 60f9a6fb4fbf..ed8fdd7060e8 100644 --- a/Modules/CIPPCore/Public/Set-CIPPMailboxType.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPMailboxType.ps1 @@ -13,13 +13,13 @@ function Set-CIPPMailboxType { try { if ([string]::IsNullOrWhiteSpace($Username)) { $Username = $UserID } $null = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Set-Mailbox' -cmdParams @{Identity = $UserID; Type = $MailboxType } -Anchor $Username - $Message = "Converted $Username to a $MailboxType mailbox" + $Message = "Successfully converted $Username to a $MailboxType mailbox" Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Info' -tenant $TenantFilter return $Message } catch { $ErrorMessage = Get-CippException -Exception $_ - $Message = "Could not convert $Username to a $MailboxType mailbox. Error: $($ErrorMessage.NormalizedError)" + $Message = "Failed to convert $Username to a $MailboxType mailbox. Error: $($ErrorMessage.NormalizedError)" Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - return $Message + throw $Message } } diff --git a/Modules/CIPPCore/Public/Set-CIPPResetPassword.ps1 b/Modules/CIPPCore/Public/Set-CIPPResetPassword.ps1 index 69b780169c69..1285bbf1f402 100644 --- a/Modules/CIPPCore/Public/Set-CIPPResetPassword.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPResetPassword.ps1 @@ -22,31 +22,35 @@ function Set-CIPPResetPassword { $null = New-GraphPostRequest -uri "https://graph.microsoft.com/v1.0/users/$($UserID)" -tenantid $TenantFilter -type PATCH -body $passwordProfile -verbose #PWPush - $PasswordLink = New-PwPushLink -Payload $password - if ($PasswordLink) { - $password = $PasswordLink + $PasswordLink = $null + try { + $PasswordLink = New-PwPushLink -Payload $password + if ($PasswordLink -and $PasswordLink -ne $false) { + $password = $PasswordLink + } + } + catch { + Write-LogMessage -headers $Headers -API $APIName -message "Failed to create PwPush link, using plain password. Error: $($_.Exception.Message)" -Sev 'Warning' -tenant $TenantFilter } - Write-LogMessage -headers $Headers -API $APIName -message "Reset the password for $DisplayName, $($UserID). User must change password is set to $forceChangePasswordNextSignIn" -Sev 'Info' -tenant $TenantFilter + Write-LogMessage -headers $Headers -API $APIName -message "Successfully reset the password for $DisplayName, $($UserID). User must change password is set to $forceChangePasswordNextSignIn" -Sev 'Info' -tenant $TenantFilter if ($UserDetails.onPremisesSyncEnabled -eq $true) { return [pscustomobject]@{ - resultText = "Reset the password for $DisplayName, $($UserID). User must change password is set to $forceChangePasswordNextSignIn. The new password is $password. WARNING: This user is AD synced. Please confirm passthrough or writeback is enabled." + resultText = "Successfully reset the password for $DisplayName, $($UserID). User must change password is set to $forceChangePasswordNextSignIn. The new password is $password. WARNING: This user is AD synced. Please confirm passthrough or writeback is enabled." copyField = $password state = 'warning' } } else { return [pscustomobject]@{ - resultText = "Reset the password for $DisplayName, $($UserID). User must change password is set to $forceChangePasswordNextSignIn. The new password is $password" + resultText = "Successfully reset the password for $DisplayName, $($UserID). User must change password is set to $forceChangePasswordNextSignIn. The new password is $password" copyField = $password state = 'success' } } } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers -API $APIName -message "Could not reset password for $DisplayName, $($UserID). Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - return [pscustomobject]@{ - resultText = "Could not reset password for $DisplayName, $($UserID). Error: $($ErrorMessage.NormalizedError)" - state = 'Error' - } + $Message = "Failed to reset password for $DisplayName, $($UserID). Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + throw $Message } } diff --git a/Modules/CIPPCore/Public/Set-CIPPSharePointPerms.ps1 b/Modules/CIPPCore/Public/Set-CIPPSharePointPerms.ps1 index 17bf2358d2de..ffc4dbd72fd6 100644 --- a/Modules/CIPPCore/Public/Set-CIPPSharePointPerms.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPSharePointPerms.ps1 @@ -42,17 +42,18 @@ function Set-CIPPSharePointPerms { $request = New-GraphPostRequest -scope "$($SharePointInfo.AdminUrl)/.default" -tenantid $TenantFilter -Uri "$($SharePointInfo.AdminUrl)/_vti_bin/client.svc/ProcessQuery" -Type POST -Body $XML -ContentType 'text/xml' # Write-Host $($request) if (!$request.ErrorInfo.ErrorMessage) { - $Message = "$($OnedriveAccessUser) has been $($RemovePermission ? 'removed from' : 'given') access to $URL" + $Message = "Successfully $($RemovePermission ? 'removed' : 'added') $($OnedriveAccessUser) as an owner of $URL" Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev Info -tenant $TenantFilter return $Message } else { - $message = "Failed to change access: $($request.ErrorInfo.ErrorMessage)" - Write-LogMessage -headers $Headers -API $APIName -message $message -Sev Error -tenant $TenantFilter + $Message = "Failed to change access: $($request.ErrorInfo.ErrorMessage)" + Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev Error -tenant $TenantFilter throw $Message } } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers -API $APIName -message "Could not add new owner to $($OnedriveAccessUser) on $URL. Error: $($ErrorMessage.NormalizedError)" -Sev Error -tenant $TenantFilter -LogData $ErrorMessage - return "Could not add owner for $($URL). Error: $($ErrorMessage.NormalizedError)" + $Message = "Failed to set SharePoint permissions for $($OnedriveAccessUser) on $URL. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev Error -tenant $TenantFilter -LogData $ErrorMessage + throw $Message } } diff --git a/Modules/CIPPCore/Public/Set-CIPPSignInState.ps1 b/Modules/CIPPCore/Public/Set-CIPPSignInState.ps1 index bf2266cae08b..ced2b88f701f 100644 --- a/Modules/CIPPCore/Public/Set-CIPPSignInState.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPSignInState.ps1 @@ -15,17 +15,18 @@ function Set-CIPPSignInState { $body = ConvertTo-Json -InputObject $body -Compress -Depth 5 $UserDetails = New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/users/$($UserID)?`$select=onPremisesSyncEnabled" -noPagination $true -tenantid $TenantFilter -verbose $null = New-GraphPostRequest -uri "https://graph.microsoft.com/v1.0/users/$($UserID)" -tenantid $TenantFilter -type PATCH -body $body -verbose - Write-LogMessage -headers $Headers -API $APIName -message "Set account enabled state to $AccountEnabled for $UserID" -Sev 'Info' -tenant $TenantFilter + Write-LogMessage -headers $Headers -API $APIName -message "Successfully set account enabled state to $AccountEnabled for $UserID" -Sev 'Info' -tenant $TenantFilter if ($UserDetails.onPremisesSyncEnabled -eq $true) { - return 'WARNING: User is AD Sync enabled. Please enable/disable in AD.' + throw "WARNING: User $UserID is AD Sync enabled. Please enable/disable in the local AD." } else { - return "Set account enabled state to $AccountEnabled for $UserID" + return "Successfully set account enabled state to $AccountEnabled for $UserID" } } catch { $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -headers $Headers -API $APIName -message "Could not disable sign in for $UserID. Error: $($ErrorMessage.NormalizedError)" -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage - return "Could not disable $UserId. Error: $($ErrorMessage.NormalizedError)" + $Message = "Failed to set sign-in state for $UserID. Error: $($ErrorMessage.NormalizedError)" + Write-LogMessage -headers $Headers -API $APIName -message $Message -Sev 'Error' -tenant $TenantFilter -LogData $ErrorMessage + throw $Message } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 index 8e119023f392..acb159e3f992 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAddDKIM.ps1 @@ -32,7 +32,7 @@ function Invoke-CIPPStandardAddDKIM { param($Tenant, $Settings) #$Rerun -Type Standard -Tenant $Tenant -API 'AddDKIM' -Settings $Settings - + Test-CIPPStandardLicense -StandardName 'AddDKIM' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access $DkimRequest = @( @{ @@ -103,7 +103,7 @@ function Invoke-CIPPStandardAddDKIM { $NewDomains = $AllDomains | Where-Object { $DKIM.Domain -notcontains $_ } $SetDomains = $DKIM | Where-Object { $AllDomains -contains $_.Domain -and $_.Enabled -eq $false } - If ($Settings.remediate -eq $true) { + if ($Settings.remediate -eq $true) { if ($null -eq $NewDomains -and $null -eq $SetDomains) { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'DKIM is already enabled for all available domains.' -sev Info diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 index b01f7b252593..2eff3aed63de 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiPhishPolicy.ps1 @@ -50,6 +50,7 @@ function Invoke-CIPPStandardAntiPhishPolicy { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'AntiPhishPolicy' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'AntiPhishPolicy' $ServicePlans = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/subscribedSkus?$select=servicePlans' -tenantid $Tenant diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiSpamSafeList.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiSpamSafeList.ps1 index ccfb85dcff9d..5ef7bd58401b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiSpamSafeList.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAntiSpamSafeList.ps1 @@ -29,6 +29,7 @@ function Invoke-CIPPStandardAntiSpamSafeList { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'AntiSpamSafeList' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'AntiSpamSafeList' try { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAppDeploy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAppDeploy.ps1 index f4c51a1a7048..1848e47918a6 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAppDeploy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAppDeploy.ps1 @@ -38,12 +38,69 @@ function Invoke-CIPPStandardAppDeploy { $Mode = $Settings.mode ?? 'copy' if ($Mode -eq 'template') { - $AppsToAdd = $Settings.templateIds.addedFields.AppId + # For template mode, we need to check each template individually + # since Gallery Templates and Enterprise Apps have different deployment methods + $AppsToAdd = @() + $Table = Get-CIPPTable -TableName 'templates' + + $AppsToAdd = foreach ($TemplateId in $Settings.templateIds.value) { + $Template = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq 'AppApprovalTemplate' and RowKey eq '$TemplateId'" + if ($Template) { + $TemplateData = $Template.JSON | ConvertFrom-Json + # Default to EnterpriseApp for backward compatibility with older templates + $AppType = $TemplateData.AppType + if (-not $AppType) { + $AppType = 'EnterpriseApp' + } + + # Return different identifiers based on app type for checking + if ($AppType -eq 'ApplicationManifest') { + # For Application Manifests, use display name for checking + $TemplateData.AppName + } elseif ($AppType -eq 'GalleryTemplate') { + # For Gallery Templates, use gallery template ID + $TemplateData.GalleryTemplateId + } else { + # For Enterprise Apps, use app ID + $TemplateData.AppId + } + } + } } - $MissingApps = foreach ($App in $AppsToAdd) { - if ($App -notin $AppExists.appId) { - $App + # Check for missing apps based on template type + $MissingApps = [System.Collections.Generic.List[string]]::new() + if ($Mode -eq 'template') { + $Table = Get-CIPPTable -TableName 'templates' + foreach ($TemplateId in $Settings.templateIds.value) { + $Template = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq 'AppApprovalTemplate' and RowKey eq '$TemplateId'" + if ($Template) { + $TemplateData = $Template.JSON | ConvertFrom-Json + $AppType = $TemplateData.AppType ?? 'EnterpriseApp' + + $IsAppMissing = $false + if ($AppType -eq 'ApplicationManifest') { + # For Application Manifests, check by display name + $IsAppMissing = $TemplateData.AppName -notin $AppExists.displayName + } elseif ($AppType -eq 'GalleryTemplate') { + # For Gallery Templates, check by application template ID + $IsAppMissing = $TemplateData.GalleryTemplateId -notin $AppExists.applicationTemplateId + } else { + # For Enterprise Apps, check by app ID + $IsAppMissing = $TemplateData.AppId -notin $AppExists.appId + } + + if ($IsAppMissing) { + $MissingApps.Add($TemplateData.AppName ?? $TemplateData.AppId ?? $TemplateData.GalleryTemplateId) + } + } + } + } else { + # For copy mode, check by app ID as before + $MissingApps = foreach ($App in $AppsToAdd) { + if ($App -notin $AppExists.appId -and $App -notin $AppExists.applicationTemplateId) { + $App + } } } if ($Settings.remediate -eq $true) { @@ -64,24 +121,125 @@ function Invoke-CIPPStandardAppDeploy { } } elseif ($Mode -eq 'template') { $TemplateIds = $Settings.templateIds.value - $TemplateName = $Settings.templateIds.label - $AppIds = $Settings.templateIds.addedFields.AppId - - foreach ($AppId in $AppIds) { - if ($AppId -notin $AppExists.appId) { - Write-Information "Adding $AppId to tenant $Tenant." - $PostResults = New-GraphPostRequest 'https://graph.microsoft.com/beta/servicePrincipals' -type POST -tenantid $Tenant -body "{ `"appId`": `"$AppId`" }" - Write-LogMessage -message "Added $AppId to tenant $Tenant" -tenant $Tenant -API 'Add Multitenant App' -sev Info - } - } + + # Get template data to determine deployment type for each template + $Table = Get-CIPPTable -TableName 'templates' + foreach ($TemplateId in $TemplateIds) { try { - Add-CIPPApplicationPermission -TemplateId $TemplateId -TenantFilter $Tenant - Add-CIPPDelegatedPermission -TemplateId $TemplateId -TenantFilter $Tenant - Write-LogMessage -API 'Standards' -tenant $tenant -message "Added application(s) from template $($TemplateName) and updated it's permissions" -sev Info + # Get the template data to determine if it's a Gallery Template or Enterprise App + $Template = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq 'AppApprovalTemplate' and RowKey eq '$TemplateId'" + + if (!$Template) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Template $TemplateId not found" -sev Error + continue + } + + $TemplateData = $Template.JSON | ConvertFrom-Json + # Default to EnterpriseApp for backward compatibility with older templates + $AppType = $TemplateData.AppType + if (-not $AppType) { + $AppType = 'EnterpriseApp' + } + + if ($AppType -eq 'GalleryTemplate') { + # Handle Gallery Template deployment + Write-Information "Deploying Gallery Template $($TemplateData.AppName) to tenant $Tenant." + + $GalleryTemplateId = $TemplateData.GalleryTemplateId + if (!$GalleryTemplateId) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Gallery Template ID not found in template data for $($TemplateData.TemplateName)" -sev Error + continue + } + + # Check if the app already exists in the tenant + if ($TemplateData.GalleryTemplateId -in $AppExists.applicationTemplateId) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Gallery Template app $($TemplateData.AppName) already exists in tenant $Tenant" -sev Info + continue + } + + # Instantiate the gallery template + $InstantiateBody = @{ + displayName = $TemplateData.AppName + } | ConvertTo-Json -Depth 10 + + $InstantiateResult = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/applicationTemplates/$GalleryTemplateId/instantiate" -type POST -tenantid $Tenant -body $InstantiateBody + + if ($InstantiateResult.application.appId) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully deployed Gallery Template $($TemplateData.AppName) to tenant $Tenant. Application ID: $($InstantiateResult.application.appId)" -sev Info + New-CIPPApplicationCopy -App $InstantiateResult.application.appId -Tenant $Tenant + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Gallery Template deployment completed but application ID not returned for $($TemplateData.AppName) in tenant $Tenant" -sev Warning + } + + } elseif ($AppType -eq 'ApplicationManifest') { + # Handle Application Manifest deployment + Write-Information "Deploying Application Manifest $($TemplateData.AppName) to tenant $Tenant." + + $ApplicationManifest = $TemplateData.ApplicationManifest + if (!$ApplicationManifest) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Application Manifest not found in template data for $($TemplateData.TemplateName)" -sev Error + continue + } + + # Check if an application with the same display name already exists + $ExistingApp = $AppExists | Where-Object { $_.displayName -eq $TemplateData.AppName } + if ($ExistingApp) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Application with name '$($TemplateData.AppName)' already exists in tenant $Tenant" -sev Info + continue + } + + $PropertiesToRemove = @('appId', 'id', 'createdDateTime', 'publisherDomain', 'servicePrincipalLockConfiguration', 'identifierUris', 'applicationIdUris') + + # Strip tenant-specific data that might cause conflicts + $CleanManifest = $ApplicationManifest | ConvertTo-Json -Depth 10 | ConvertFrom-Json + foreach ($Property in $PropertiesToRemove) { + $CleanManifest.PSObject.Properties.Remove($Property) + } + # Create the application from manifest + try { + $CreateBody = $CleanManifest | ConvertTo-Json -Depth 10 + $CreatedApp = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/applications' -type POST -tenantid $Tenant -body $CreateBody + + if ($CreatedApp.appId) { + # Create service principal for the application + $ServicePrincipalBody = @{ + appId = $CreatedApp.appId + } | ConvertTo-Json + + $ServicePrincipal = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/servicePrincipals' -type POST -tenantid $Tenant -body $ServicePrincipalBody + + Write-LogMessage -API 'Standards' -tenant $tenant -message "Successfully deployed Application Manifest $($TemplateData.AppName) to tenant $Tenant. Application ID: $($CreatedApp.appId)" -sev Info + + if ($CreatedApp.requiredResourceAccess) { + Add-CIPPDelegatedPermission -RequiredResourceAccess $CreatedApp.requiredResourceAccess -ApplicationId $CreatedApp.appId -Tenantfilter $Tenant + Add-CIPPApplicationPermission -RequiredResourceAccess $CreatedApp.requiredResourceAccess -ApplicationId $CreatedApp.appId -Tenantfilter $Tenant + } + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Application Manifest deployment failed - no application ID returned for $($TemplateData.AppName) in tenant $Tenant" -sev Error + } + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Error creating application from manifest in tenant $Tenant - $($_.Exception.Message)" -sev Error + } + + } else { + # Handle Enterprise App deployment (existing logic) + $AppId = $TemplateData.AppId + if ($AppId -notin $AppExists.appId) { + Write-Information "Adding $AppId to tenant $Tenant." + $PostResults = New-GraphPostRequest 'https://graph.microsoft.com/beta/servicePrincipals' -type POST -tenantid $Tenant -body "{ `"appId`": `"$AppId`" }" + Write-LogMessage -message "Added $AppId to tenant $Tenant" -tenant $Tenant -API 'Standards' -sev Info + } + + # Apply permissions for Enterprise Apps + Add-CIPPApplicationPermission -TemplateId $TemplateId -TenantFilter $Tenant + Add-CIPPDelegatedPermission -TemplateId $TemplateId -TenantFilter $Tenant + Write-LogMessage -API 'Standards' -tenant $tenant -message "Added application $($TemplateData.AppName) from Enterprise App template and updated its permissions" -sev Info + } + } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to add app from approval template $($TemplateName). Error: $ErrorMessage" -sev Error + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to deploy template $TemplateId. Error: $ErrorMessage" -sev Error } } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 index bed3d5c48109..2c0009db686b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAtpPolicyForO365.ps1 @@ -31,6 +31,7 @@ function Invoke-CIPPStandardAtpPolicyForO365 { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'AtpPolicyForO365' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'AtpPolicyForO365' try { $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AtpPolicyForO365' | @@ -41,8 +42,8 @@ function Invoke-CIPPStandardAtpPolicyForO365 { } } $StateIsCorrect = ($CurrentState.EnableATPForSPOTeamsODB -eq $true) -and - ($CurrentState.EnableSafeDocs -eq $true) -and - ($CurrentState.AllowSafeDocsOpen -eq $Settings.AllowSafeDocsOpen) + ($CurrentState.EnableSafeDocs -eq $true) -and + ($CurrentState.AllowSafeDocsOpen -eq $Settings.AllowSafeDocsOpen) if ($Settings.remediate -eq $true) { if ($StateIsCorrect -eq $true) { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 index e7a19162c0fb..f0963a92e1bf 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuditLog.ps1 @@ -32,6 +32,7 @@ function Invoke-CIPPStandardAuditLog { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'AuditLog' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'AuditLog' Write-Host ($Settings | ConvertTo-Json) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuthMethodsPolicyMigration.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuthMethodsPolicyMigration.ps1 new file mode 100644 index 000000000000..2d40d7a7e266 --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAuthMethodsPolicyMigration.ps1 @@ -0,0 +1,59 @@ +function Invoke-CIPPStandardAuthMethodsPolicyMigration { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) AuthMethodsPolicyMigration + .SYNOPSIS + (Label) Complete Authentication Methods Policy Migration + .DESCRIPTION + (Helptext) Completes the migration of authentication methods policy to the new format + (DocsDescription) Sets the authentication methods policy migration state to complete. This is required when migrating from legacy authentication policies to the new unified authentication methods policy. + .NOTES + CAT + Entra (AAD) Standards + TAG + ADDEDCOMPONENT + IMPACT + Medium Impact + ADDEDDATE + 2025-01-08 + POWERSHELLEQUIVALENT + Update-MgBetaPolicyAuthenticationMethodPolicy + RECOMMENDEDBY + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards + #> + + param($Tenant, $Settings) + $CurrentInfo = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy' -tenantid $Tenant + + if ($Settings.remediate -eq $true) { + if ($CurrentInfo.policyMigrationState -eq 'migrationComplete') { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Authentication methods policy migration is already complete.' -sev Info + } else { + try { + New-GraphPOSTRequest -uri 'https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy' -tenantid $Tenant -body '{"policyMigrationState": "migrationComplete"}' -type PATCH + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Authentication methods policy migration completed successfully.' -sev Info + } catch { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to complete authentication methods policy migration: $($_.Exception.Message)" -sev Error + } + } + } + + if ($Settings.alert -eq $true) { + if ($CurrentInfo.policyMigrationState -ne 'migrationComplete') { + Write-StandardsAlert -message 'Authentication methods policy migration is not complete. Please check if you have legacy SSPR settings or MFA settings set: https://learn.microsoft.com/en-us/entra/identity/authentication/how-to-authentication-methods-manage' -object $CurrentInfo -tenant $tenant -standardName 'AuthMethodsPolicyMigration' -standardId $Settings.standardId + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Authentication methods policy migration is not complete' -sev Alert + } + } + + if ($Settings.report -eq $true) { + $migrationComplete = $CurrentInfo.policyMigrationState -eq 'migrationComplete' + Set-CIPPStandardsCompareField -FieldName 'standards.AuthMethodsPolicyMigration' -FieldValue $migrationComplete -TenantFilter $tenant + Add-CIPPBPAField -FieldName 'AuthMethodsPolicyMigration' -FieldValue $migrationComplete -StoreAs bool -Tenant $tenant + } + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoExpandArchive.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoExpandArchive.ps1 index 14d1b614fc2b..f78e231977c3 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoExpandArchive.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutoExpandArchive.ps1 @@ -28,6 +28,7 @@ function Invoke-CIPPStandardAutoExpandArchive { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'AutoExpandArchive' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'AutoExpandArchive' $CurrentState = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig').AutoExpandingArchiveEnabled diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotProfile.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotProfile.ps1 index 041628368288..9639d3c93c5e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotProfile.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotProfile.ps1 @@ -40,6 +40,7 @@ function Invoke-CIPPStandardAutopilotProfile { https://docs.cipp.app/user-documentation/tenant/standards/list-standards #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'AutopilotProfile' -TenantFilter $Tenant -RequiredCapabilities @('INTUNE_A', 'MDM_Services', 'EMS', 'SCCM', 'MICROSOFTINTUNEPLAN1') # Get the current configuration try { @@ -47,8 +48,8 @@ function Invoke-CIPPStandardAutopilotProfile { $DisplayName = Get-CIPPTextReplacement -Text $Settings.DisplayName -TenantFilter $Tenant $CurrentConfig = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeploymentProfiles' -tenantid $Tenant | - Where-Object { $_.displayName -eq $DisplayName } | - Select-Object -Property displayName, description, deviceNameTemplate, language, enableWhiteGlove, extractHardwareHash, outOfBoxExperienceSetting, preprovisioningAllowed + Where-Object { $_.displayName -eq $DisplayName } | + Select-Object -Property displayName, description, deviceNameTemplate, language, enableWhiteGlove, extractHardwareHash, outOfBoxExperienceSetting, preprovisioningAllowed if ($Settings.NotLocalAdmin -eq $true) { $userType = 'Standard' } else { $userType = 'Administrator' } if ($Settings.SelfDeployingMode -eq $true) { $DeploymentMode = 'shared' } else { $DeploymentMode = 'singleUser' } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotStatusPage.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotStatusPage.ps1 index e8957cb84d8c..bd6f0e055860 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotStatusPage.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardAutopilotStatusPage.ps1 @@ -36,6 +36,7 @@ function Invoke-CIPPStandardAutopilotStatusPage { https://docs.cipp.app/user-documentation/tenant/standards/list-standards #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'AutopilotStatusPage' -TenantFilter $Tenant -RequiredCapabilities @('INTUNE_A', 'MDM_Services', 'EMS', 'SCCM', 'MICROSOFTINTUNEPLAN1') # Get current Autopilot enrollment status page configuration try { @@ -43,13 +44,13 @@ function Invoke-CIPPStandardAutopilotStatusPage { Select-Object -Property id, displayName, priority, showInstallationProgress, blockDeviceSetupRetryByUser, allowDeviceResetOnInstallFailure, allowLogCollectionOnInstallFailure, customErrorMessage, installProgressTimeoutInMinutes, allowDeviceUseOnInstallFailure, trackInstallProgressForAutopilotOnly $StateIsCorrect = ($CurrentConfig.installProgressTimeoutInMinutes -eq $Settings.TimeOutInMinutes) -and - ($CurrentConfig.customErrorMessage -eq $Settings.ErrorMessage) -and - ($CurrentConfig.showInstallationProgress -eq $Settings.ShowProgress) -and - ($CurrentConfig.allowLogCollectionOnInstallFailure -eq $Settings.EnableLog) -and - ($CurrentConfig.trackInstallProgressForAutopilotOnly -eq $Settings.OBEEOnly) -and - ($CurrentConfig.blockDeviceSetupRetryByUser -eq !$Settings.BlockDevice) -and - ($CurrentConfig.allowDeviceResetOnInstallFailure -eq $Settings.AllowReset) -and - ($CurrentConfig.allowDeviceUseOnInstallFailure -eq $Settings.AllowFail) + ($CurrentConfig.customErrorMessage -eq $Settings.ErrorMessage) -and + ($CurrentConfig.showInstallationProgress -eq $Settings.ShowProgress) -and + ($CurrentConfig.allowLogCollectionOnInstallFailure -eq $Settings.EnableLog) -and + ($CurrentConfig.trackInstallProgressForAutopilotOnly -eq $Settings.OBEEOnly) -and + ($CurrentConfig.blockDeviceSetupRetryByUser -eq !$Settings.BlockDevice) -and + ($CurrentConfig.allowDeviceResetOnInstallFailure -eq $Settings.AllowReset) -and + ($CurrentConfig.allowDeviceUseOnInstallFailure -eq $Settings.AllowFail) } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to check Autopilot Enrollment Status Page: $ErrorMessage" -sev Error @@ -57,7 +58,7 @@ function Invoke-CIPPStandardAutopilotStatusPage { } # Remediate if the state is not correct - If ($Settings.remediate -eq $true) { + if ($Settings.remediate -eq $true) { try { $Parameters = @{ TenantFilter = $Tenant diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 index 67d733214ee7..8cd144e22988 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardBookings.ps1 @@ -29,6 +29,7 @@ function Invoke-CIPPStandardBookings { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'Bookings' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'Bookings' # Get state value using null-coalescing operator diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 index 194596088dfe..ab5e26c6fbce 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCloudMessageRecall.ps1 @@ -29,10 +29,11 @@ function Invoke-CIPPStandardCloudMessageRecall { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'CloudMessageRecall' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'CloudMessageRecall' # Get state value using null-coalescing operator - $state = $Settings.state.value ?? $Settings.state + $state = $Settings.state.value $CurrentState = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig').MessageRecallEnabled $WantedState = if ($state -eq 'true') { $true } else { $false } @@ -41,14 +42,14 @@ function Invoke-CIPPStandardCloudMessageRecall { if ($Settings.report -eq $true) { # Default is not set, not set means it's enabled if ($null -eq $CurrentState ) { $CurrentState = $true } - Set-CIPPStandardsCompareField -FieldName 'standards.CloudMessageRecall' -FieldValue $CurrentState -TenantFilter $Tenant + Set-CIPPStandardsCompareField -FieldName 'standards.CloudMessageRecall' -FieldValue $StateIsCorrect -TenantFilter $Tenant Add-CIPPBPAField -FieldName 'MessageRecall' -FieldValue $CurrentState -StoreAs bool -Tenant $Tenant } # Input validation if (([string]::IsNullOrWhiteSpace($state) -or $state -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'MessageRecallEnabled: Invalid state parameter set' -sev Error - Return + return } if ($Settings.remediate -eq $true) { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccessTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccessTemplate.ps1 index 3220da6c44f0..880cce989772 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccessTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardConditionalAccessTemplate.ps1 @@ -30,22 +30,36 @@ function Invoke-CIPPStandardConditionalAccessTemplate { #> param($Tenant, $Settings) ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'ConditionalAccess' + Test-CIPPStandardLicense -StandardName 'ConditionalAccessTemplate' -TenantFilter $Tenant -RequiredCapabilities @('AAD_PREMIUM', 'AAD_PREMIUM_P2') - If ($Settings.remediate -eq $true) { - + if ($Settings.remediate -eq $true) { + $AllCAPolicies = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/identity/conditionalAccess/policies?$top=999' -tenantid $Tenant foreach ($Setting in $Settings) { try { - $Table = Get-CippTable -tablename 'templates' $Filter = "PartitionKey eq 'CATemplate' and RowKey eq '$($Setting.TemplateList.value)'" $JSONObj = (Get-CippAzDataTableEntity @Table -Filter $Filter).JSON - $null = New-CIPPCAPolicy -replacePattern 'displayName' -TenantFilter $tenant -state $Setting.state -RawJSON $JSONObj -Overwrite $true -APIName $APIName -Headers $Request.Headers + $null = New-CIPPCAPolicy -replacePattern 'displayName' -TenantFilter $tenant -state $Setting.state -RawJSON $JSONObj -Overwrite $true -APIName $APIName -Headers $Request.Headers -DisableSD $Setting.DisableSD } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message Write-LogMessage -API 'Standards' -tenant $tenant -message "Failed to create or update conditional access rule $($JSONObj.displayName). Error: $ErrorMessage" -sev 'Error' } } - - + } + if ($Settings.report -eq $true) { + $Policies = $Settings.TemplateList.JSON | ConvertFrom-Json -Depth 10 + #check if all groups.displayName are in the existingGroups, if not $fieldvalue should contain all missing groups, else it should be true. + $MissingPolicies = foreach ($policy in $Policies) { + $CheckExististing = $AllCAPolicies | Where-Object -Property displayName -EQ $policy.displayname + if (!$CheckExististing) { + $policy.displayname + } + } + if ($MissingPolicies.Count -eq 0) { + $fieldValue = $true + } else { + $fieldValue = $MissingPolicies -join ', ' + } + Set-CIPPStandardsCompareField -FieldName 'standards.ConditionalAccessTemplate' -FieldValue $fieldValue -Tenant $Tenant } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCustomBannedPasswordList.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCustomBannedPasswordList.ps1 new file mode 100644 index 000000000000..5191bf2cc04c --- /dev/null +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardCustomBannedPasswordList.ps1 @@ -0,0 +1,238 @@ +function Invoke-CIPPStandardCustomBannedPasswordList { + <# + .FUNCTIONALITY + Internal + .COMPONENT + (APIName) CustomBannedPasswordList + .SYNOPSIS + (Label) Update Entra ID Custom Banned Password List + .DESCRIPTION + (Helptext) Updates the Entra ID custom banned password list with organization-specific terms. Requires Entra ID P1 or P2 licenses. Enter words separated by commas or new lines. Each word must be 4-16 characters long. Maximum 1,000 words allowed. + (DocsDescription) Updates the Entra ID custom banned password list with organization-specific terms that should be blocked from user passwords. This supplements the global banned password list maintained by Microsoft. The custom list is limited to 1,000 key base terms of 4-16 characters each. Entra ID will block variations and combinations of these terms in user passwords. + .NOTES + CAT + Global Standards + TAG + "CIS M365 5.0 (5.2.3.2)" + ADDEDCOMPONENT + {"type":"textArea","name":"standards.CustomBannedPasswordList.BannedWords","label":"Banned Words List","placeholder":"Enter banned words separated by commas or new lines (4-16 characters each, max 1000 words)","required":true,"rows":10} + IMPACT + Medium Impact + ADDEDDATE + 2025-06-28 + POWERSHELLEQUIVALENT + Get-MgBetaDirectorySetting, New-MgBetaDirectorySetting, Update-MgBetaDirectorySetting + RECOMMENDEDBY + "CIS", "CIPP" + UPDATECOMMENTBLOCK + Run the Tools\Update-StandardsComments.ps1 script to update this comment block + .LINK + https://docs.cipp.app/user-documentation/tenant/standards/list-standards + #> + + param($Tenant, $Settings) + + $PasswordRuleTemplateId = '5cf42378-d67d-4f36-ba46-e8b86229381d' + + # Parse and validate banned words from input + $BannedWordsInput = $Settings.BannedWords + if ([string]::IsNullOrWhiteSpace($BannedWordsInput)) { + Write-LogMessage -API 'Standards' -tenant $tenant -message 'CustomBannedPasswordList: No banned words provided' -sev Error + return + } + + # Split input by commas, newlines, or semicolons and clean up + $BannedWordsList = $BannedWordsInput -split '[,;\r\n]+' | ForEach-Object { ($_.Trim()) } | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | Select-Object -Unique + + # Validate word count + if ($BannedWordsList.Count -gt 1000) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "CustomBannedPasswordList: Too many banned words provided ($($BannedWordsList.Count)). Maximum allowed is 1000." -sev Error + return + } + + # Validate word length (4-16 characters), remove duplicates and invalid words + $ValidBannedWordsList = [System.Collections.Generic.List[string]]::new() + $InvalidWords = [System.Collections.Generic.List[string]]::new() + + foreach ($Word in $BannedWordsList) { + if ($Word.Length -ge 4 -and $Word.Length -le 16) { + $ValidBannedWordsList.Add($Word) + } else { + $InvalidWords.Add($Word) + } + } + $BannedWordsList = $ValidBannedWordsList | Select-Object -Unique + + # Alert if invalid words are found + if ($InvalidWords.Count -gt 0) { + Write-LogMessage -API 'Standards' -tenant $tenant -message "CustomBannedPasswordList: Invalid words found in input (must be 4-16 characters). Please remove the following words: $($InvalidWords -join ', ')" -sev Warning + } + + # Get existing directory settings for password rules + try { + $ExistingSettings = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/settings' -tenantid $Tenant | Where-Object { $_.templateId -eq $PasswordRuleTemplateId } + } catch { + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to get existing Custom Banned Password List: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage + return + } + + if ($Settings.remediate -eq $true) { + Write-Host 'Time to remediate Custom Banned Password List' + + if ($null -eq $ExistingSettings) { + Write-Host 'No existing Custom Banned Password List found, creating new one' + # Create new directory setting with default values if it doesn't exist + try { + $Body = @{ + templateId = $PasswordRuleTemplateId + values = @( + @{ + name = 'EnableBannedPasswordCheck' + value = 'True' + } + @{ + name = 'BannedPasswordList' + value = $BannedWordsList -join ([char]9) + } + @{ + name = 'LockoutDurationInSeconds' + value = '60' + } + @{ + name = 'LockoutThreshold' + value = '10' + } + @{ + name = 'EnableBannedPasswordCheckOnPremises' + value = 'False' + } + @{ + name = 'BannedPasswordCheckOnPremisesMode' + value = 'Audit' + } + ) + } + $JsonBody = ConvertTo-Json -Depth 10 -InputObject $Body -Compress + + $ExistingSettings = New-GraphPostRequest -tenantid $Tenant -Uri 'https://graph.microsoft.com/beta/settings' -Type POST -Body $JsonBody + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Custom Banned Password List created with $($BannedWordsList.Count) words." -sev Info + } catch { + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to create Custom Banned Password List: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage + } + } else { + Write-Host 'Existing Custom Banned Password List found, updating it' + # Update existing directory setting + try { + # Get the current passwords and check if all the new words are already in the list + $CurrentBannedWords = $ExistingSettings.values | Where-Object { $_.name -eq 'BannedPasswordList' } + $CurrentBannedWords = $CurrentBannedWords.value -split ([char]9) + + # Check if the new words are already in the list + $NewBannedWords = $BannedWordsList | Where-Object { $CurrentBannedWords -notcontains $_ } + if ($NewBannedWords.Count -eq 0 -and ($ExistingSettings.values | Where-Object { $_.name -eq 'EnableBannedPasswordCheck' }).value -eq 'True') { + Write-Host 'No new words to add' + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Custom Banned Password List is already configured with $($CurrentBannedWords.Count) words." -sev Info + } else { + Write-Host "$($NewBannedWords.Count) new words to add" + $AllBannedWords = [System.Collections.Generic.List[string]]::new() + $NewBannedWords | ForEach-Object { $AllBannedWords.Add($_) } + $CurrentBannedWords | ForEach-Object { $AllBannedWords.Add($_) } + $AllBannedWords = $AllBannedWords | Select-Object -Unique -First 1000 | Where-Object { $_ -ne $null } + + $Body = @{ + values = @( + @{ + name = 'EnableBannedPasswordCheck' + value = 'True' + } + @{ + name = 'BannedPasswordList' + value = $AllBannedWords -join ([char]9) + } + @{ + name = 'LockoutDurationInSeconds' + value = ($ExistingSettings.values | Where-Object { $_.name -eq 'LockoutDurationInSeconds' }).value + } + @{ + name = 'LockoutThreshold' + value = ($ExistingSettings.values | Where-Object { $_.name -eq 'LockoutThreshold' }).value + } + @{ + name = 'EnableBannedPasswordCheckOnPremises' + value = ($ExistingSettings.values | Where-Object { $_.name -eq 'EnableBannedPasswordCheckOnPremises' }).value + } + @{ + name = 'BannedPasswordCheckOnPremisesMode' + value = ($ExistingSettings.values | Where-Object { $_.name -eq 'BannedPasswordCheckOnPremisesMode' }).value + } + ) + } + + $JsonBody = ConvertTo-Json -Depth 10 -InputObject $Body -Compress + $null = New-GraphPostRequest -tenantid $Tenant -Uri "https://graph.microsoft.com/beta/settings/$($ExistingSettings.id)" -Type PATCH -Body $JsonBody + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Custom Banned Password List updated with $($NewBannedWords.Count) new words." -sev Info + } + + } catch { + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Failed to update Custom Banned Password List: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage + } + } + } + + if ($Settings.alert -eq $true) { + if ($null -eq $ExistingSettings) { + Write-StandardsAlert -message 'Custom Banned Password List is not configured' -object @{Status = 'Not Configured'; WordCount = 0 } -tenant $tenant -standardName 'CustomBannedPasswordList' -standardId $Settings.standardId + Write-LogMessage -API 'Standards' -tenant $tenant -message 'Custom Banned Password List is not configured' -sev Info + } else { + $BannedPasswordCheckEnabled = $ExistingSettings.values | Where-Object { $_.name -eq 'EnableBannedPasswordCheck' } + $CurrentBannedWords = $ExistingSettings.values | Where-Object { $_.name -eq 'BannedPasswordList' } + $CurrentBannedWords = if ($CurrentBannedWords.value) { ($CurrentBannedWords.value -split ([char]9)) } else { @() } + + # Find missing words from input + $MissingInputWords = $BannedWordsList | Where-Object { $CurrentBannedWords -notcontains $_ } + + if ($MissingInputWords.Count -gt 0) { + Write-StandardsAlert -message "Custom Banned Password List is missing $($MissingInputWords.Count) input words: $($MissingInputWords -join ', ')" -object @{Status = 'Configured but Missing Input Words'; MissingWords = $MissingInputWords; Enabled = $BannedPasswordCheckEnabled.value } -tenant $tenant -standardName 'CustomBannedPasswordList' -standardId $Settings.standardId + Write-LogMessage -API 'Standards' -tenant $tenant -message "Custom Banned Password List is missing $($MissingInputWords.Count) input words: $($MissingInputWords -join ', ')" -sev Info + } else { + Write-LogMessage -API 'Standards' -tenant $tenant -message "Custom Banned Password List contains all input words ($($BannedWordsList.Count))." -sev Info + } + } + } + + if ($Settings.report -eq $true) { + if ($null -eq $ExistingSettings) { + $BannedPasswordState = @{ + Status = 'Not Configured' + Enabled = $false + WordCount = 0 + Compliant = $false + MissingInputWords = $BannedWordsList + } + } else { + $BannedPasswordCheckEnabled = $ExistingSettings.values | Where-Object { $_.name -eq 'EnableBannedPasswordCheck' } + $CurrentBannedWords = $ExistingSettings.values | Where-Object { $_.name -eq 'BannedPasswordList' } + $CurrentBannedWords = if ($CurrentBannedWords.value) { ($CurrentBannedWords.value -split ([char]9)) } else { @() } + $CurrentWordCount = $CurrentBannedWords.Count + + # Find missing words from input + $MissingInputWords = $BannedWordsList | Where-Object { $CurrentBannedWords -notcontains $_ } + + $BannedPasswordState = @{ + Status = 'Configured' + Enabled = $BannedPasswordCheckEnabled.value -eq 'True' + WordCount = $CurrentWordCount + Compliant = ($BannedPasswordCheckEnabled.value -eq 'True' -and $MissingInputWords.Count -eq 0) + MissingInputWords = $MissingInputWords + } + } + + Add-CIPPBPAField -FieldName 'CustomBannedPasswordList' -FieldValue $BannedPasswordState -StoreAs json -Tenant $tenant + Set-CIPPStandardsCompareField -FieldName 'standards.CustomBannedPasswordList' -FieldValue $BannedPasswordState.Compliant -Tenant $tenant + } + + +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDefaultPlatformRestrictions.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDefaultPlatformRestrictions.ps1 index cc7c578585bf..e5cd404006f2 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDefaultPlatformRestrictions.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDefaultPlatformRestrictions.ps1 @@ -38,6 +38,7 @@ function Invoke-CIPPStandardDefaultPlatformRestrictions { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'DefaultPlatformRestrictions' -TenantFilter $Tenant -RequiredCapabilities @('INTUNE_A', 'MDM_Services', 'EMS', 'SCCM', 'MICROSOFTINTUNEPLAN1') try { $CurrentState = New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/deviceManagement/deviceEnrollmentConfigurations?`$expand=assignments&orderBy=priority&`$filter=deviceEnrollmentConfigurationType eq 'SinglePlatformRestriction'" -tenantID $Tenant -AsApp $true | diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDefaultSharingLink.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDefaultSharingLink.ps1 index 9093ab528e51..25f0900ec3c5 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDefaultSharingLink.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDefaultSharingLink.ps1 @@ -7,20 +7,22 @@ function Invoke-CIPPStandardDefaultSharingLink { .SYNOPSIS (Label) Set Default Sharing Link Settings .DESCRIPTION - (Helptext) Sets the default sharing link type to Internal and permission to View in SharePoint and OneDrive. - (DocsDescription) Sets the default sharing link type to Internal and permission to View in SharePoint and OneDrive. + (Helptext) Configure the SharePoint default sharing link type and permission. This setting controls both the type of sharing link created by default and the permission level assigned to those links. + (DocsDescription) Sets the default sharing link type (Direct or Internal) and permission (View) in SharePoint and OneDrive. Direct sharing means links only work for specific people, while Internal sharing means links work for anyone in the organization. .NOTES CAT SharePoint Standards TAG ADDEDCOMPONENT + [{"type":"autoComplete","multiple":false,"creatable":false,"label":"Default Sharing Link Type","name":"standards.DefaultSharingLink.SharingLinkType","options":[{"label":"Direct - Only specific people","value":"Direct"},{"label":"Internal - Anyone in the organization","value":"Internal"}]}] IMPACT Medium Impact ADDEDDATE 2025-06-13 POWERSHELLEQUIVALENT - Set-SPOTenant -DefaultSharingLinkType Internal -DefaultLinkPermission View + Set-SPOTenant -DefaultSharingLinkType [Direct|Internal] -DefaultLinkPermission View RECOMMENDEDBY + CIS UPDATECOMMENTBLOCK Run the Tools\Update-StandardsComments.ps1 script to update this comment block .LINK @@ -28,36 +30,65 @@ function Invoke-CIPPStandardDefaultSharingLink { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'DefaultSharingLink' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') - $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | - Select-Object -Property DefaultSharingLinkType, DefaultLinkPermission + # Determine the desired sharing link type (default to Internal if not specified) + $DesiredSharingLinkType = $Settings.SharingLinkType.value ?? 'Internal' + + # Map the string values to numeric values for SharePoint + $SharingLinkTypeMap = @{ + 'Direct' = 1 + 'Internal' = 2 + 'Anyone' = 3 + } + $DesiredSharingLinkTypeValue = $SharingLinkTypeMap[$DesiredSharingLinkType] - $StateIsCorrect = ($CurrentState.DefaultSharingLinkType -eq 2) -and ($CurrentState.DefaultLinkPermission -eq 1) + $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | + Select-Object -Property _ObjectIdentity_, TenantFilter, DefaultSharingLinkType, DefaultLinkPermission + # Check if the current state matches the desired configuration + $StateIsCorrect = ($CurrentState.DefaultSharingLinkType -eq $DesiredSharingLinkTypeValue) -and ($CurrentState.DefaultLinkPermission -eq 1) + Write-Host "currentstate: $($CurrentState.DefaultSharingLinkType), $($CurrentState.DefaultLinkPermission). Desired: $DesiredSharingLinkTypeValue, 1" if ($Settings.remediate -eq $true) { if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Default sharing link settings are already configured correctly' -Sev Info + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Default sharing link settings are already configured correctly (Type: $DesiredSharingLinkType, Permission: View)" -Sev Info } else { $Properties = @{ - DefaultSharingLinkType = 2 # Internal + DefaultSharingLinkType = $DesiredSharingLinkTypeValue DefaultLinkPermission = 1 # View } try { - Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully set default sharing link settings' -Sev Info + $CurrentState | Set-CIPPSPOTenant -Properties $Properties + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Successfully set default sharing link settings (Type: $DesiredSharingLinkType, Permission: View)" -Sev Info } catch { - $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to set default sharing link settings. Error: $ErrorMessage" -Sev Error + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Failed to set default sharing link settings. Error: $($ErrorMessage.NormalizedError)" -Sev Error -LogData $ErrorMessage } } } if ($Settings.alert -eq $true) { if ($StateIsCorrect -eq $true) { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Default sharing link settings are configured correctly' -Sev Info + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Default sharing link settings are configured correctly (Type: $DesiredSharingLinkType, Permission: View)" -Sev Info } else { - Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Default sharing link settings are not configured correctly' -Sev Alert + # Determine current values for alert message + $CurrentSharingType = switch ($CurrentState.DefaultSharingLinkType) { + 1 { 'Direct' } + 2 { 'Internal' } + 3 { 'Anyone' } + default { 'Unknown' } + } + $CurrentPermission = switch ($CurrentState.DefaultLinkPermission) { + 0 { 'Edit' } + 1 { 'View' } + 2 { 'Edit' } + default { 'Unknown' } + } + + $Message = "Default sharing link settings are not configured correctly. Current: Type=$CurrentSharingType, Permission=$CurrentPermission. Expected: Type=$DesiredSharingLinkType, Permission=View" + Write-StandardsAlert -message $Message -object $CurrentState -tenant $Tenant -standardName 'DefaultSharingLink' -standardId $Settings.standardId + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message $Message -Sev Alert } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 index 322dce4b8c8b..309dec178cc5 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDelegateSentItems.ps1 @@ -29,6 +29,7 @@ function Invoke-CIPPStandardDelegateSentItems { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'DelegateSentItems' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access #$Rerun -Type Standard -Tenant $Tenant -API 'DelegateSentItems' -Settings $Settings diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 index f6cbe319cab9..4819b976a842 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeletedUserRentention.ps1 @@ -29,6 +29,7 @@ function Invoke-CIPPStandardDeletedUserRentention { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'DeletedUserRentention' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'DeletedUserRetention' $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeployContactTemplates.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeployContactTemplates.ps1 index 26a3f61a0d12..0b2a65d1b82a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeployContactTemplates.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeployContactTemplates.ps1 @@ -32,6 +32,7 @@ function Invoke-CIPPStandardDeployContactTemplates { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'DeployContactTemplates' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access $APIName = 'Standards' diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeployMailContact.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeployMailContact.ps1 index 4f991c25be1f..df818e2903e2 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeployMailContact.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeployMailContact.ps1 @@ -33,6 +33,7 @@ function Invoke-CIPPStandardDeployMailContact { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'DeployMailContact' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access # Input validation if ([string]::IsNullOrWhiteSpace($Settings.DisplayName)) { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 index cf37d42fa516..ece57aabcd53 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAddShortcutsToOneDrive.ps1 @@ -29,6 +29,7 @@ function Invoke-CIPPStandardDisableAddShortcutsToOneDrive { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'DisableAddShortcutsToOneDrive' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'DisableAddShortcutsToOneDrive' $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | Select-Object _ObjectIdentity_, TenantFilter, DisableAddToOneDrive diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAdditionalStorageProviders.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAdditionalStorageProviders.ps1 index 74ca49628813..e7d2c22ceb70 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAdditionalStorageProviders.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableAdditionalStorageProviders.ps1 @@ -31,6 +31,7 @@ function Invoke-CIPPStandardDisableAdditionalStorageProviders { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'DisableAdditionalStorageProviders' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'DisableAdditionalStorageProviders' $AdditionalStorageProvidersState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OwaMailboxPolicy' -cmdParams @{Identity = 'OwaMailboxPolicy-Default' } -Select 'Identity, AdditionalStorageProvidersAvailable' diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 index 9dba24fe66bb..5438ece03e33 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 @@ -30,6 +30,7 @@ function Invoke-CIPPStandardDisableBasicAuthSMTP { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'DisableBasicAuthSMTP' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'DisableBasicAuthSMTP' $CurrentInfo = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-TransportConfig' diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExchangeOnlinePowerShell.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExchangeOnlinePowerShell.ps1 index 33b0ab22ed63..cf319d6a3410 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExchangeOnlinePowerShell.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExchangeOnlinePowerShell.ps1 @@ -33,6 +33,7 @@ function Invoke-CIPPStandardDisableExchangeOnlinePowerShell { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'DisableExchangeOnlinePowerShell' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'DisableExchangeOnlinePowerShell' try { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExternalCalendarSharing.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExternalCalendarSharing.ps1 index 71024b35dad2..4fb615e4de48 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExternalCalendarSharing.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableExternalCalendarSharing.ps1 @@ -31,6 +31,7 @@ function Invoke-CIPPStandardDisableExternalCalendarSharing { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'DisableExternalCalendarSharing' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'DisableExternalCalendarSharing' $CurrentInfo = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SharingPolicy' | Where-Object { $_.Default -eq $true } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableM365GroupUsers.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableM365GroupUsers.ps1 index f6fc18ff4b30..b5089fd60555 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableM365GroupUsers.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableM365GroupUsers.ps1 @@ -28,6 +28,7 @@ function Invoke-CIPPStandardDisableM365GroupUsers { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'DisableM365GroupUsers' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'DisableM365GroupUsers' $CurrentState = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/settings' -tenantid $tenant) | Where-Object -Property displayname -EQ 'Group.unified' diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 index f098710e5e57..3f63b9d87948 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableOutlookAddins.ps1 @@ -31,6 +31,7 @@ function Invoke-CIPPStandardDisableOutlookAddins { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'DisableOutlookAddins' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'DisableOutlookAddins' $CurrentInfo = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-RoleAssignmentPolicy' | Where-Object { $_.IsDefault -eq $true } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 index c6aa08a66250..52b81c6fd596 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableReshare.ps1 @@ -31,6 +31,7 @@ function Invoke-CIPPStandardDisableReshare { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'DisableReshare' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'DisableReshare' $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableResourceMailbox.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableResourceMailbox.ps1 index dca3fceecf40..2dcbc902afd0 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableResourceMailbox.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableResourceMailbox.ps1 @@ -31,6 +31,7 @@ function Invoke-CIPPStandardDisableResourceMailbox { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'DisableResourceMailbox' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'DisableResourceMailbox' # Get all users that are able to be diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharePointLegacyAuth.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharePointLegacyAuth.ps1 index 5e63504dccea..8d7aea7e0ffd 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharePointLegacyAuth.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableSharePointLegacyAuth.ps1 @@ -32,6 +32,7 @@ function Invoke-CIPPStandardDisableSharePointLegacyAuth { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'DisableSharePointLegacyAuth' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'DisableSharePointLegacyAuth' $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings?$select=isLegacyAuthProtocolsEnabled' -tenantid $Tenant -AsApp $true diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 index be6f3437ba1e..e1162ce67cb9 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableTNEF.ps1 @@ -30,7 +30,7 @@ function Invoke-CIPPStandardDisableTNEF { param ($Tenant, $Settings) ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'DisableTNEF' - + Test-CIPPStandardLicense -StandardName 'DisableTNEF' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-RemoteDomain' -cmdParams @{Identity = 'Default' } if ($Settings.remediate -eq $true) { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 index 144eec1b1fdf..8e849780f752 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableUserSiteCreate.ps1 @@ -28,6 +28,7 @@ function Invoke-CIPPStandardDisableUserSiteCreate { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'DisableUserSiteCreate' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'DisableUserSiteCreate' $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 index e75909d94c41..e9a7ebbbe710 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXODisableAutoForwarding.ps1 @@ -33,6 +33,7 @@ function Invoke-CIPPStandardEXODisableAutoForwarding { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'EXODisableAutoForwarding' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'EXODisableAutoForwarding' $CurrentInfo = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-HostedOutboundSpamFilterPolicy' -cmdParams @{Identity = 'Default' } -useSystemMailbox $true diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXOOutboundSpamLimits.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXOOutboundSpamLimits.ps1 index e596c065199b..ca9e7b77be9e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXOOutboundSpamLimits.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEXOOutboundSpamLimits.ps1 @@ -35,6 +35,7 @@ function Invoke-CIPPStandardEXOOutboundSpamLimits { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'EXOOutboundSpamLimits' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access # Make sure it handles the frontend being both autocomplete and a text field $ActionWhenThresholdReached = $Settings.ActionWhenThresholdReached.value ?? $Settings.ActionWhenThresholdReached diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableCustomerLockbox.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableCustomerLockbox.ps1 index 729c765dcc9f..dc3a11f960ef 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableCustomerLockbox.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableCustomerLockbox.ps1 @@ -32,6 +32,7 @@ function Invoke-CIPPStandardEnableCustomerLockbox { param($Tenant, $Settings) ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'EnableCustomerLockbox' + Test-CIPPStandardLicense -StandardName 'EnableCustomerLockbox' -TenantFilter $Tenant -RequiredCapabilities @('CustomerLockbox') $CustomerLockboxStatus = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig').CustomerLockboxEnabled if ($Settings.remediate -eq $true) { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableLitigationHold.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableLitigationHold.ps1 index 4fe60d3f807d..1ad012205c4c 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableLitigationHold.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableLitigationHold.ps1 @@ -29,6 +29,7 @@ function Invoke-CIPPStandardEnableLitigationHold { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'EnableLitigationHold' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$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' } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 index 9c948ccfda1a..8f8bffe8c893 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailTips.ps1 @@ -33,6 +33,7 @@ function Invoke-CIPPStandardEnableMailTips { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'EnableMailTips' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'EnableMailTips' $MailTipsState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig' | Select-Object MailTipsAllTipsEnabled, MailTipsExternalRecipientsTipsEnabled, MailTipsGroupMetricsEnabled, MailTipsLargeAudienceThreshold diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 index e23baaf3aeb7..a700051aa4d5 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableMailboxAuditing.ps1 @@ -32,6 +32,7 @@ function Invoke-CIPPStandardEnableMailboxAuditing { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'EnableMailboxAuditing' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'EnableMailboxAuditing' $AuditState = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig').AuditDisabled diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 index 4ec2259debd7..40557d9e72ab 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableOnlineArchiving.ps1 @@ -28,6 +28,7 @@ function Invoke-CIPPStandardEnableOnlineArchiving { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'EnableOnlineArchiving' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'EnableOnlineArchiving' $MailboxPlans = @( 'ExchangeOnline', 'ExchangeOnlineEnterprise' ) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExConnector.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExConnector.ps1 index d32d5008f175..5cd6d0252cab 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExConnector.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExConnector.ps1 @@ -4,6 +4,7 @@ function Invoke-CIPPStandardExConnector { Internal #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'ExConnector' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'ExConnector' If ($Settings.remediate -eq $true) { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 index bec921cca4cf..c7ebbb9b4285 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExcludedfileExt.ps1 @@ -29,6 +29,7 @@ function Invoke-CIPPStandardExcludedfileExt { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'ExcludedfileExt' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'ExcludedfileExt' $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 index 99dcf906b2d8..05320c8fbb03 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardExternalMFATrusted.ps1 @@ -43,7 +43,7 @@ function Invoke-CIPPStandardExternalMFATrusted { # Input validation if (([string]::IsNullOrWhiteSpace($state) -or $state -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'ExternalMFATrusted: Invalid state parameter set' -sev Error - Return + return } if ($Settings.remediate -eq $true) { @@ -66,7 +66,8 @@ function Invoke-CIPPStandardExternalMFATrusted { } if ($Settings.report -eq $true) { $state = $ExternalMFATrusted.inboundTrust.isMfaAccepted ? $true : $ExternalMFATrusted.inboundTrust - Set-CIPPStandardsCompareField -FieldName 'standards.ExternalMFATrusted' -FieldValue $ExternalMFATrusted.inboundTrust.isMfaAccepted -TenantFilter $Tenant + $ReportState = $ExternalMFATrusted.inboundTrust.isMfaAccepted -eq $WantedState + Set-CIPPStandardsCompareField -FieldName 'standards.ExternalMFATrusted' -FieldValue $ReportState -TenantFilter $Tenant Add-CIPPBPAField -FieldName 'ExternalMFATrusted' -FieldValue $ExternalMFATrusted.inboundTrust.isMfaAccepted -StoreAs bool -Tenant $Tenant } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 index d15885b99102..490799dba5f9 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardFocusedInbox.ps1 @@ -29,6 +29,7 @@ function Invoke-CIPPStandardFocusedInbox { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'FocusedInbox' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'FocusedInbox' # Get state value using null-coalescing operator diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 index 9f93f49538c5..4e461388872e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGlobalQuarantineNotifications.ps1 @@ -30,7 +30,7 @@ function Invoke-CIPPStandardGlobalQuarantineNotifications { param ($Tenant, $Settings) ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'GlobalQuarantineNotifications' - + Test-CIPPStandardLicense -StandardName 'GlobalQuarantineNotifications' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-QuarantinePolicy' -cmdParams @{ QuarantinePolicyType = 'GlobalQuarantinePolicy' } | Select-Object -ExcludeProperty '*data.type' # This might take the cake on ugly hacky stuff i've done, diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 index 0fed0c046031..b3f0dec77263 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 @@ -28,8 +28,9 @@ function Invoke-CIPPStandardGroupTemplate { https://docs.cipp.app/user-documentation/tenant/standards/list-standards #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'GroupTemplate' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'GroupTemplate' - + $existingGroups = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/groups?$top=999' -tenantid $tenant if ($Settings.remediate -eq $true) { #Because the list name changed from TemplateList to groupTemplate by someone :@, we'll need to set it back to TemplateList $Settings.groupTemplate ? ($Settings | Add-Member -NotePropertyName 'TemplateList' -NotePropertyValue $Settings.groupTemplate) : $null @@ -40,7 +41,7 @@ function Invoke-CIPPStandardGroupTemplate { $Filter = "PartitionKey eq 'GroupTemplate' and RowKey eq '$($Template.value)'" $groupobj = (Get-AzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json $email = if ($groupobj.domain) { "$($groupobj.username)@$($groupobj.domain)" } else { "$($groupobj.username)@$($Tenant)" } - $CheckExististing = New-GraphGETRequest -uri 'https://graph.microsoft.com/beta/groups?$top=999' -tenantid $tenant | Where-Object -Property displayName -EQ $groupobj.displayname + $CheckExististing = $existingGroups | Where-Object -Property displayName -EQ $groupobj.displayname $BodyToship = [pscustomobject] @{ 'displayName' = $groupobj.Displayname 'description' = $groupobj.Description @@ -114,4 +115,22 @@ function Invoke-CIPPStandardGroupTemplate { } } } + if ($Settings.report -eq $true) { + $Groups = $Settings.groupTemplate.JSON | ConvertFrom-Json -Depth 10 + #check if all groups.displayName are in the existingGroups, if not $fieldvalue should contain all missing groups, else it should be true. + $MissingGroups = foreach ($Group in $Groups) { + $CheckExististing = $existingGroups | Where-Object -Property displayName -EQ $Group.displayname + if (!$CheckExististing) { + $Group.displayname + } + } + + if ($MissingGroups.Count -eq 0) { + $fieldValue = $true + } else { + $fieldValue = $MissingGroups -join ', ' + } + + Set-CIPPStandardsCompareField -FieldName 'standards.GroupTemplate' -FieldValue $fieldValue -Tenant $Tenant + } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 index c1d0bdfe93ca..2d041d1d4efa 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneComplianceSettings.ps1 @@ -30,6 +30,7 @@ function Invoke-CIPPStandardIntuneComplianceSettings { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'IntuneComplianceSettings' -TenantFilter $Tenant -RequiredCapabilities @('INTUNE_A', 'MDM_Services', 'EMS', 'SCCM', 'MICROSOFTINTUNEPLAN1') $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/deviceManagement/settings' -tenantid $Tenant | Select-Object secureByDefault, deviceComplianceCheckinThresholdDays diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 index ac90ae92bc35..ed722cf5f482 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardIntuneTemplate.ps1 @@ -31,6 +31,7 @@ function Invoke-CIPPStandardIntuneTemplate { https://docs.cipp.app/user-documentation/tenant/standards/list-standards #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'IntuneTemplate' -TenantFilter $Tenant -RequiredCapabilities @('INTUNE_A', 'MDM_Services', 'EMS', 'SCCM', 'MICROSOFTINTUNEPLAN1') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'intuneTemplate' $Table = Get-CippTable -tablename 'templates' $Filter = "PartitionKey eq 'IntuneTemplate'" diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMDMScope.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMDMScope.ps1 index e49351739558..2605df158452 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMDMScope.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMDMScope.ps1 @@ -30,6 +30,7 @@ function Invoke-CIPPStandardMDMScope { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'MDMScope' -TenantFilter $Tenant -RequiredCapabilities @('INTUNE_A', 'MDM_Services', 'EMS', 'SCCM', 'MICROSOFTINTUNEPLAN1') $CurrentInfo = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/policies/mobileDeviceManagementPolicies/0000000a-0000-0000-c000-000000000000?$expand=includedGroups' -tenantid $Tenant diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMailboxRecipientLimits.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMailboxRecipientLimits.ps1 index 6f57d05f687c..6837f85b456f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMailboxRecipientLimits.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMailboxRecipientLimits.ps1 @@ -30,6 +30,7 @@ function Invoke-CIPPStandardMailboxRecipientLimits { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'MailboxRecipientLimits' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access # Input validation if ([Int32]$Settings.RecipientLimit -lt 0 -or [Int32]$Settings.RecipientLimit -gt 10000) { @@ -69,8 +70,11 @@ function Invoke-CIPPStandardMailboxRecipientLimits { if ($null -ne $Mailboxes -and @($Mailboxes).Count -gt 0) { # Process mailboxes and categorize them based on their plan limits $MailboxResults = @($Mailboxes) | ForEach-Object { - $Mailbox = $_ + $Mailbox = $_ + if ($Mailbox.UserPrincipalName -like 'DiscoverySearchMailbox*' -or $Mailbox.UserPrincipalName -like 'SystemMailbox*') { + return + } # Safe hashtable lookup - check if MailboxPlanId exists and is not null $Plan = $null if ($Mailbox.MailboxPlanId -and $MailboxPlanLookup.ContainsKey($Mailbox.MailboxPlanId)) { @@ -83,8 +87,7 @@ function Invoke-CIPPStandardMailboxRecipientLimits { # If mailbox has "Unlimited" set but has a plan, use the plan's limit as the current limit $CurrentLimit = if ($Mailbox.RecipientLimits -eq 'Unlimited') { $PlanMaxRecipients - } - else { + } else { $Mailbox.RecipientLimits } @@ -96,15 +99,13 @@ function Invoke-CIPPStandardMailboxRecipientLimits { PlanLimit = $PlanMaxRecipients PlanName = $Plan.DisplayName } - } - elseif ($CurrentLimit -ne $Settings.RecipientLimit) { + } elseif ($CurrentLimit -ne $Settings.RecipientLimit) { [PSCustomObject]@{ Type = 'ToUpdate' Mailbox = $Mailbox } } - } - elseif ($Mailbox.RecipientLimits -ne $Settings.RecipientLimit) { + } elseif ($Mailbox.RecipientLimits -ne $Settings.RecipientLimit) { [PSCustomObject]@{ Type = 'ToUpdate' Mailbox = $Mailbox @@ -139,11 +140,11 @@ function Invoke-CIPPStandardMailboxRecipientLimits { $MailboxChanges = $MailboxesToUpdate | ForEach-Object { $CurrentLimit = if ($_.RecipientLimits -eq 'Unlimited') { 'Unlimited' } else { $_.RecipientLimits } @{ - Identity = $_.Identity - DisplayName = $_.DisplayName + Identity = $_.Identity + DisplayName = $_.DisplayName PrimarySmtpAddress = $_.PrimarySmtpAddress - CurrentLimit = $CurrentLimit - NewLimit = $Settings.RecipientLimit + CurrentLimit = $CurrentLimit + NewLimit = $Settings.RecipientLimit } } @@ -165,13 +166,11 @@ function Invoke-CIPPStandardMailboxRecipientLimits { # Execute batch update $null = New-ExoBulkRequest -tenantid $Tenant -cmdletArray $UpdateRequests Write-LogMessage -API 'Standards' -tenant $Tenant -message "Successfully applied recipient limits to $($MailboxesToUpdate.Count) mailboxes" -sev Info - } - catch { + } catch { $ErrorMessage = Get-CippException -Exception $_ Write-LogMessage -API 'Standards' -tenant $Tenant -message "Could not set recipient limits. $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage } - } - else { + } else { Write-LogMessage -API 'Standards' -tenant $Tenant -message "All mailboxes already have the correct recipient limit of $($Settings.RecipientLimit)" -sev Info } } @@ -180,12 +179,11 @@ function Invoke-CIPPStandardMailboxRecipientLimits { if ($Settings.alert -eq $true) { if ($MailboxesToUpdate.Count -eq 0 -and $MailboxesWithPlanIssues.Count -eq 0) { Write-LogMessage -API 'Standards' -tenant $Tenant -message "All mailboxes have the correct recipient limit of $($Settings.RecipientLimit)" -sev Info - } - else { + } else { # Create structured alert data $AlertData = @{ - RequestedLimit = $Settings.RecipientLimit - MailboxesToUpdate = @() + RequestedLimit = $Settings.RecipientLimit + MailboxesToUpdate = @() MailboxesWithPlanIssues = @() } @@ -197,11 +195,11 @@ function Invoke-CIPPStandardMailboxRecipientLimits { $AlertData.MailboxesToUpdate = $MailboxesToUpdate | ForEach-Object { $CurrentLimit = if ($_.RecipientLimits -eq 'Unlimited') { 'Unlimited' } else { $_.RecipientLimits } @{ - Identity = $_.Identity - DisplayName = $_.DisplayName + Identity = $_.Identity + DisplayName = $_.DisplayName PrimarySmtpAddress = $_.PrimarySmtpAddress - CurrentLimit = $CurrentLimit - RequiredLimit = $Settings.RecipientLimit + CurrentLimit = $CurrentLimit + RequiredLimit = $Settings.RecipientLimit } } # Add to alert objects list efficiently @@ -214,10 +212,10 @@ function Invoke-CIPPStandardMailboxRecipientLimits { if ($MailboxesWithPlanIssues.Count -gt 0) { $AlertData.MailboxesWithPlanIssues = $MailboxesWithPlanIssues | ForEach-Object { @{ - Identity = $_.Identity - CurrentLimit = $_.CurrentLimit - PlanLimit = $_.PlanLimit - PlanName = $_.PlanName + Identity = $_.Identity + CurrentLimit = $_.CurrentLimit + PlanLimit = $_.PlanLimit + PlanName = $_.PlanName RequestedLimit = $Settings.RecipientLimit } } @@ -249,8 +247,7 @@ function Invoke-CIPPStandardMailboxRecipientLimits { if ($MailboxesToUpdate.Count -eq 0 -and $MailboxesWithPlanIssues.Count -eq 0) { $FieldValue = $true - } - else { + } else { $FieldValue = $ReportData } Set-CIPPStandardsCompareField -FieldName 'standards.MailboxRecipientLimits' -FieldValue $FieldValue -Tenant $Tenant diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 index 42e34db49f3a..a450b1cfcb5d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMalwareFilterPolicy.ps1 @@ -40,6 +40,7 @@ function Invoke-CIPPStandardMalwareFilterPolicy { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'MalwareFilterPolicy' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'MalwareFilterPolicy' $PolicyList = @('CIPP Default Malware Policy', 'Default Malware Policy') diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMessageExpiration.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMessageExpiration.ps1 index 4a46e10ac85c..31d6e06b558f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMessageExpiration.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMessageExpiration.ps1 @@ -28,6 +28,7 @@ function Invoke-CIPPStandardMessageExpiration { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'MessageExpiration' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'MessageExpiration' $MessageExpiration = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-TransportConfig').messageExpiration diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOutBoundSpamAlert.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOutBoundSpamAlert.ps1 index bcf78c7d5f73..dcef35ba6fc7 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOutBoundSpamAlert.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOutBoundSpamAlert.ps1 @@ -31,6 +31,7 @@ function Invoke-CIPPStandardOutBoundSpamAlert { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'OutBoundSpamAlert' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access $CurrentInfo = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-HostedOutboundSpamFilterPolicy' -cmdParams @{ Identity = 'Default' } -useSystemMailbox $true diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishSimSpoofIntelligence.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishSimSpoofIntelligence.ps1 index 12bcc2280571..3544fa6f3b6f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishSimSpoofIntelligence.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishSimSpoofIntelligence.ps1 @@ -30,6 +30,7 @@ function Invoke-CIPPStandardPhishSimSpoofIntelligence { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'PhishSimSpoofIntelligence' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access # 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 diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishingSimulations.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishingSimulations.ps1 index 742871deffa8..8d59019bd04c 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishingSimulations.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardPhishingSimulations.ps1 @@ -32,6 +32,7 @@ function Invoke-CIPPStandardPhishingSimulations { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'PhishingSimulations' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access $PolicyName = 'CIPPPhishSim' # Fetch current Phishing Simulations Policy settings and ensure it is correctly configured diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardProfilePhotos.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardProfilePhotos.ps1 index 2eb1b6222131..85e1d560ba4b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardProfilePhotos.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardProfilePhotos.ps1 @@ -29,6 +29,7 @@ function Invoke-CIPPStandardProfilePhotos { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'ProfilePhotos' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access # Get state value using null-coalescing operator $StateValue = $Settings.state.value ?? $Settings.state diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 index 782d847ec8a1..7be58341e296 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineRequestAlert.ps1 @@ -29,7 +29,7 @@ function Invoke-CIPPStandardQuarantineRequestAlert { #> param ($Tenant, $Settings) - + Test-CIPPStandardLicense -StandardName 'QuarantineRequestAlert' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access $PolicyName = 'CIPP User requested to release a quarantined message' $CurrentState = New-ExoRequest -TenantId $Tenant -cmdlet 'Get-ProtectionAlert' -Compliance | diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineTemplate.ps1 index 4f76c8f4378c..263cc6267802 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardQuarantineTemplate.ps1 @@ -40,6 +40,7 @@ function Invoke-CIPPStandardQuarantineTemplate { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'QuarantineTemplate' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access $APIName = 'Standards' diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRestrictThirdPartyStorageServices.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRestrictThirdPartyStorageServices.ps1 index 9ee55cba203d..d67437a3412f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRestrictThirdPartyStorageServices.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRestrictThirdPartyStorageServices.ps1 @@ -31,6 +31,7 @@ function Invoke-CIPPStandardRestrictThirdPartyStorageServices { param ($Tenant, $Settings) ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'RestrictThirdPartyStorageServices' + Test-CIPPStandardLicense -StandardName 'ThirdPartyStorageServicesRestricted' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') $AppId = 'c1f33bc0-bdb4-4248-ba9b-096807ddb43e' $Uri = "https://graph.microsoft.com/beta/servicePrincipals?`$filter=appId eq '$AppId'" @@ -40,7 +41,7 @@ function Invoke-CIPPStandardRestrictThirdPartyStorageServices { } catch { $ErrorMessage = Get-CippException -Exception $_ Write-LogMessage -API 'Standards' -tenant $Tenant -message "Could not get current state for Microsoft 365 on the web service principal. Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage - Return + return } if ($Settings.remediate -eq $true) { @@ -59,7 +60,7 @@ function Invoke-CIPPStandardRestrictThirdPartyStorageServices { # Normal /servicePrincipal/AppId does not find the service principal, so gotta use the Upsert method. Also handles if the service principal does not exist nicely. # https://learn.microsoft.com/en-us/graph/api/serviceprincipal-upsert?view=graph-rest-beta&tabs=http $UpdateUri = "https://graph.microsoft.com/beta/servicePrincipals(appId='$AppId')" - $null = New-GraphPostRequest -Uri $UpdateUri -Body $DisableBody -TenantID $Tenant -Type PATCH -AddedHeaders @{'Prefer' = 'create-if-missing'} + $null = New-GraphPostRequest -Uri $UpdateUri -Body $DisableBody -TenantID $Tenant -Type PATCH -AddedHeaders @{'Prefer' = 'create-if-missing' } # Refresh the current state after disabling $CurrentState = New-GraphGetRequest -Uri $Uri -tenantid $Tenant | Select-Object displayName, accountEnabled, appId diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 index 77587b18e6ab..942757d4b6d1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRetentionPolicyTag.ps1 @@ -29,6 +29,7 @@ function Invoke-CIPPStandardRetentionPolicyTag { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'RetentionPolicyTag' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access $PolicyName = 'CIPP Deleted Items' $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-RetentionPolicyTag' | diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 index 178f2fe033c4..629271841f61 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardRotateDKIM.ps1 @@ -31,6 +31,7 @@ function Invoke-CIPPStandardRotateDKIM { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'RotateDKIM' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access $DKIM = (New-ExoRequest -tenantid $tenant -cmdlet 'Get-DkimSigningConfig') | Where-Object { $_.Selector1KeySize -eq 1024 -and $_.Enabled -eq $true } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPAzureB2B.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPAzureB2B.ps1 index 016f4697e400..db4febf857ba 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPAzureB2B.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPAzureB2B.ps1 @@ -30,9 +30,10 @@ function Invoke-CIPPStandardSPAzureB2B { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'SPAzureB2B' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | - Select-Object -Property EnableAzureADB2BIntegration + Select-Object -Property _ObjectIdentity_, TenantFilter, EnableAzureADB2BIntegration $StateIsCorrect = ($CurrentState.EnableAzureADB2BIntegration -eq $true) @@ -45,7 +46,7 @@ function Invoke-CIPPStandardSPAzureB2B { } try { - Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties + $CurrentState | Set-CIPPSPOTenant -Properties $Properties Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully set the SharePoint Azure B2B to enabled' -Sev Info } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDirectSharing.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDirectSharing.ps1 index e91952957966..8b73d0189817 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDirectSharing.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDirectSharing.ps1 @@ -31,9 +31,12 @@ function Invoke-CIPPStandardSPDirectSharing { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'SPDirectSharing' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') + + Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'This standard has been deprecated in favor of the "Set Default Sharing Link Settings" standard. Please update your standards to use new standard. However this will continue to function.' -Sev Alert $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | - Select-Object -Property DefaultSharingLinkType + Select-Object -Property _ObjectIdentity_, TenantFilter, DefaultSharingLinkType $StateIsCorrect = ($CurrentState.DefaultSharingLinkType -eq 'Direct' -or $CurrentState.DefaultSharingLinkType -eq 1) @@ -46,7 +49,7 @@ function Invoke-CIPPStandardSPDirectSharing { } try { - Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties + $CurrentState | Set-CIPPSPOTenant -Properties $Properties Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully set the SharePoint Default Direct Sharing to Direct' -Sev Info } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisableLegacyWorkflows.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisableLegacyWorkflows.ps1 index 57a4f292367c..2e8193c31f37 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisableLegacyWorkflows.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisableLegacyWorkflows.ps1 @@ -27,6 +27,7 @@ function Invoke-CIPPStandardSPDisableLegacyWorkflows { https://docs.cipp.app/user-documentation/tenant/standards/list-standards #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'SPDisableLegacyWorkflows' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | Select-Object -Property * @@ -46,7 +47,7 @@ function Invoke-CIPPStandardSPDisableLegacyWorkflows { } try { - Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties + $CurrentState | Set-CIPPSPOTenant -Properties $Properties Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully disabled Legacy Workflows' -Sev Info } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisallowInfectedFiles.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisallowInfectedFiles.ps1 index c61ec77268fb..0be5d526cc8d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisallowInfectedFiles.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPDisallowInfectedFiles.ps1 @@ -31,9 +31,10 @@ function Invoke-CIPPStandardSPDisallowInfectedFiles { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'SPDisallowInfectedFiles' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | - Select-Object -Property DisallowInfectedFileDownload + Select-Object -Property _ObjectIdentity_, TenantFilter, DisallowInfectedFileDownload $StateIsCorrect = ($CurrentState.DisallowInfectedFileDownload -eq $true) @@ -46,7 +47,7 @@ function Invoke-CIPPStandardSPDisallowInfectedFiles { } try { - Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties + $CurrentState | Set-CIPPSPOTenant -Properties $Properties Write-LogMessage -API 'Standards' -tenant $tenant -Message 'Successfully disallowed downloading SharePoint infected files.' -Sev Info } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPEmailAttestation.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPEmailAttestation.ps1 index c26879a60c2b..9d2e3e10f2f0 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPEmailAttestation.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPEmailAttestation.ps1 @@ -32,8 +32,9 @@ function Invoke-CIPPStandardSPEmailAttestation { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'SPEmailAttestation' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') - $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | Select-Object -Property EmailAttestationReAuthDays, EmailAttestationRequired + $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | Select-Object -Property _ObjectIdentity_, TenantFilter, EmailAttestationReAuthDays, EmailAttestationRequired $StateIsCorrect = ($CurrentState.EmailAttestationReAuthDays -eq [int]$Settings.Days) -and ($CurrentState.EmailAttestationRequired -eq $true) @@ -48,7 +49,7 @@ function Invoke-CIPPStandardSPEmailAttestation { } try { - $Response = Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties + $Response = $CurrentState | 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 re-authentication with verification code restriction. Error: $ErrorMessage" -Sev Error diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 index 7db6ed6a53e1..092871783f84 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPExternalUserExpiration.ps1 @@ -31,9 +31,10 @@ function Invoke-CIPPStandardSPExternalUserExpiration { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'SPExternalUserExpiration' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | - Select-Object -Property ExternalUserExpireInDays, ExternalUserExpirationRequired + Select-Object -Property _ObjectIdentity_, TenantFilter, ExternalUserExpireInDays, ExternalUserExpirationRequired $StateIsCorrect = ($CurrentState.ExternalUserExpireInDays -eq $Settings.Days) -and ($CurrentState.ExternalUserExpirationRequired -eq $true) @@ -48,7 +49,7 @@ function Invoke-CIPPStandardSPExternalUserExpiration { } try { - Get-CIPPSPOTenant -TenantFilter $Tenant | Set-CIPPSPOTenant -Properties $Properties + $CurrentState | Set-CIPPSPOTenant -Properties $Properties Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'Successfully set External User Expiration' -Sev Info } catch { $ErrorMessage = Get-CippException -Exception $_ diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPSyncButtonState.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPSyncButtonState.ps1 index ba222bb08412..da7dec54aa6a 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPSyncButtonState.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSPSyncButtonState.ps1 @@ -29,6 +29,7 @@ function Invoke-CIPPStandardSPSyncButtonState { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'SPSyncButtonState' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | Select-Object _ObjectIdentity_, TenantFilter, HideSyncButtonOnDocLib diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 index edd59d6cbaa4..06788c6859f1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 @@ -37,6 +37,7 @@ function Invoke-CIPPStandardSafeAttachmentPolicy { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'SafeAttachmentPolicy' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access $ServicePlans = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/subscribedSkus?$select=servicePlans' -tenantid $Tenant $ServicePlans = $ServicePlans.servicePlans.servicePlanName diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 index e360efddabf2..9150e3dd5437 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksPolicy.ps1 @@ -36,6 +36,7 @@ function Invoke-CIPPStandardSafeLinksPolicy { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'SafeLinksPolicy' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access $ServicePlans = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/subscribedSkus?$select=servicePlans' -tenantid $Tenant $ServicePlans = $ServicePlans.servicePlans.servicePlanName diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksTemplatePolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksTemplatePolicy.ps1 index 00d71e371b2b..1c570ee3518b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksTemplatePolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeLinksTemplatePolicy.ps1 @@ -29,6 +29,7 @@ function Invoke-CIPPStandardSafeLinksTemplatePolicy { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'SafeLinksTemplatePolicy' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access Write-LogMessage -API 'Standards' -tenant $Tenant -message "Processing SafeLinks template with settings: $($Settings | ConvertTo-Json -Compress)" -sev Debug diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 index 00c5f576900d..736f7dcee5c3 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeSendersDisable.ps1 @@ -31,6 +31,7 @@ function Invoke-CIPPStandardSafeSendersDisable { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'SafeSendersDisable' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access if ($Settings.remediate -eq $true) { try { @@ -62,4 +63,9 @@ function Invoke-CIPPStandardSafeSendersDisable { } } + if ($Settings.report -eq $true) { + #This script always returns true, as it only disables the Safe Senders list + Set-CIPPStandardsCompareField -FieldName 'standards.SafeSendersDisable' -FieldValue $true -Tenant $Tenant + } + } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 index 8577b4368988..9f4b73d5bf89 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendFromAlias.ps1 @@ -29,11 +29,12 @@ function Invoke-CIPPStandardSendFromAlias { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'SendFromAlias' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access $CurrentInfo = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-OrganizationConfig').SendFromAliasEnabled if ($Settings.remediate -eq $true) { - if ($CurrentInfo -eq $false) { + if ($CurrentInfo -ne $true) { try { New-ExoRequest -tenantid $Tenant -cmdlet 'Set-OrganizationConfig' -cmdParams @{ SendFromAliasEnabled = $true } Write-LogMessage -API 'Standards' -tenant $tenant -message 'Send from alias enabled.' -sev Info diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 index 333788bf51e0..eac18fe134af 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSendReceiveLimitTenant.ps1 @@ -30,6 +30,7 @@ function Invoke-CIPPStandardSendReceiveLimitTenant { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'SendReceiveLimitTenant' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access # Input validation if ([Int32]$Settings.SendLimit -lt 1 -or [Int32]$Settings.SendLimit -gt 150) { @@ -37,31 +38,21 @@ function Invoke-CIPPStandardSendReceiveLimitTenant { return } + # Input validation if ([Int32]$Settings.ReceiveLimit -lt 1 -or [Int32]$Settings.ReceiveLimit -gt 150) { Write-LogMessage -API 'Standards' -tenant $tenant -message 'SendReceiveLimitTenant: Invalid ReceiveLimit parameter set' -sev Error return } + $AllMailBoxPlans = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-MailboxPlan' | Select-Object DisplayName, MaxSendSize, MaxReceiveSize, GUID - $MaxSendSize = "$($Settings.SendLimit)MB" - $MaxReceiveSize = "$($Settings.ReceiveLimit)MB" - $MaxSendSizeBytes = $Settings.SendLimit * 1MB - $MaxReceiveSizeBytes = $Settings.ReceiveLimit * 1MB + $MaxSendSize = [int64]"$($Settings.SendLimit)MB" + $MaxReceiveSize = [int64]"$($Settings.ReceiveLimit)MB" $NotSetCorrectly = foreach ($MailboxPlan in $AllMailBoxPlans) { - if ($MailboxPlan.MaxSendSize -eq 'Unlimited') { - $PlanMaxSendSize = [int64]::MaxValue - } else { - $PlanMaxSendSize = [int64]($MailboxPlan.MaxSendSize -replace '.*\(([\d,]+).*', '$1' -replace ',', '') - } - - if ($MailboxPlan.MaxReceiveSize -eq 'Unlimited') { - $PlanMaxReceiveSize = [int64]::MaxValue - } else { - $PlanMaxReceiveSize = [int64]($MailboxPlan.MaxReceiveSize -replace '.*\(([\d,]+).*', '$1' -replace ',', '') - } - - if ($PlanMaxSendSize -ne $MaxSendSizeBytes -or $PlanMaxReceiveSize -ne $MaxReceiveSizeBytes) { + $PlanMaxSendSize = [int64]($MailboxPlan.MaxSendSize -replace '.*\(([\d,]+).*', '$1' -replace ',', '') + $PlanMaxReceiveSize = [int64]($MailboxPlan.MaxReceiveSize -replace '.*\(([\d,]+).*', '$1' -replace ',', '') + if ($PlanMaxSendSize -ne $MaxSendSize -or $PlanMaxReceiveSize -ne $MaxReceiveSize) { $MailboxPlan } } @@ -86,6 +77,7 @@ function Invoke-CIPPStandardSendReceiveLimitTenant { } if ($Settings.alert -eq $true) { + if ($NotSetCorrectly.Count -eq 0) { Write-LogMessage -API 'Standards' -tenant $tenant -message "The tenant send($($Settings.SendLimit)MB) and receive($($Settings.ReceiveLimit)MB) limits are set correctly" -sev Info } else { diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSharePointMassDeletionAlert.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSharePointMassDeletionAlert.ps1 index cad89dfd0049..770dfb0d8d72 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSharePointMassDeletionAlert.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSharePointMassDeletionAlert.ps1 @@ -31,6 +31,7 @@ function Invoke-CIPPStandardSharePointMassDeletionAlert { #> param ($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'DeletedUserRentention' -TenantFilter $Tenant -RequiredCapabilities @('RMS_S_PREMIUM2') $PolicyName = 'CIPP SharePoint mass deletion of files by a user' @@ -42,9 +43,9 @@ function Invoke-CIPPStandardSharePointMassDeletionAlert { $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) + ($MissingEmailsInSettings.Count -eq 0) -and + ($CurrentState.Threshold -eq $Settings.Threshold) -and + ($CurrentState.TimeWindow -eq $Settings.TimeWindow) $CompareField = [PSCustomObject]@{ 'Threshold' = $CurrentState.Threshold @@ -52,10 +53,10 @@ function Invoke-CIPPStandardSharePointMassDeletionAlert { 'NotifyUser' = $CurrentState.NotifyUser -join ', ' } - If ($Settings.remediate -eq $true) { - If ($StateIsCorrect -eq $true) { + 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 { + } else { $cmdParams = @{ 'NotifyUser' = $Settings.NotifyUser.value 'Category' = 'DataGovernance' @@ -66,7 +67,7 @@ function Invoke-CIPPStandardSharePointMassDeletionAlert { 'TimeWindow' = $Settings.TimeWindow } - If ($CurrentState.Name -eq $PolicyName) { + if ($CurrentState.Name -eq $PolicyName) { try { $cmdParams['Identity'] = $PolicyName New-ExoRequest -TenantId $Tenant -cmdlet 'Set-ProtectionAlert' -Compliance -cmdParams $cmdParams -UseSystemMailbox $true @@ -75,7 +76,7 @@ function Invoke-CIPPStandardSharePointMassDeletionAlert { $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 { + } else { try { $cmdParams['name'] = $PolicyName $cmdParams['ThreatType'] = 'Activity' @@ -90,16 +91,16 @@ function Invoke-CIPPStandardSharePointMassDeletionAlert { } } - If ($Settings.alert -eq $true) { - If ($StateIsCorrect -eq $true) { + 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 { + } else { Write-StandardsAlert -message 'SharePoint mass deletion of files alert is disabled' -object $CompareField -tenant $tenant -standardName 'SharePointMassDeletionAlert' -standardId $Settings.standardId Write-LogMessage -API 'Standards' -Tenant $Tenant -Message 'SharePoint mass deletion of files alert is disabled' -sev Info } } - If ($Settings.report -eq $true) { + if ($Settings.report -eq $true) { $FieldValue = $StateIsCorrect ? $true : $CompareField Set-CIPPStandardsCompareField -FieldName 'standards.SharePointMassDeletionAlert' -FieldValue $FieldValue -TenantFilter $Tenant Add-CIPPBPAField -FieldName 'SharePointMassDeletionAlert' -FieldValue [bool]$StateIsCorrect -StoreAs bool -Tenant $Tenant diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 index a92efc0b4b32..6575803545b6 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardShortenMeetings.ps1 @@ -31,6 +31,7 @@ function Invoke-CIPPStandardShortenMeetings { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'ShortenMeetings' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access Write-Host "ShortenMeetings: $($Settings | ConvertTo-Json -Compress)" # Get state value using null-coalescing operator $scopeDefault = $Settings.ShortenEventScopeDefault.value ? $Settings.ShortenEventScopeDefault.value : $Settings.ShortenEventScopeDefault diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 index c650c95ef858..e0b8f403788e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 @@ -51,6 +51,7 @@ function Invoke-CIPPStandardSpamFilterPolicy { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'SpamFilterPolicy' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access $PolicyName = 'CIPP Default Spam Filter Policy' diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 index 076829cac9f3..2b3e72b02a66 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 @@ -33,6 +33,7 @@ function Invoke-CIPPStandardSpoofWarn { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'SpoofWarn' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access $CurrentInfo = (New-ExoRequest -tenantid $Tenant -cmdlet 'Get-ExternalInOutlook') diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 index e85947eca52c..d7ec04d2c1d9 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardStaleEntraDevices.ps1 @@ -32,6 +32,7 @@ function Invoke-CIPPStandardStaleEntraDevices { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'StaleEntraDevices' -TenantFilter $Tenant -RequiredCapabilities @('INTUNE_A', 'MDM_Services', 'EMS', 'SCCM', 'MICROSOFTINTUNEPLAN1') # Get all Entra devices $AllDevices = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/devices' -tenantid $Tenant | Where-Object { $null -ne $_.approximateLastSignInDateTime } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEmailIntegration.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEmailIntegration.ps1 index d54b70a00796..63c7d1e182a3 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEmailIntegration.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEmailIntegration.ps1 @@ -30,6 +30,7 @@ Function Invoke-CIPPStandardTeamsEmailIntegration { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'TeamsEmailIntegration' -TenantFilter $Tenant -RequiredCapabilities @('MCOSTANDARD', 'MCOEV', 'MCOIMP', 'TEAMS1','Teams_Room_Standard') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsEmailIntegration' $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsClientConfiguration' -CmdParams @{Identity = 'Global' } | Select-Object AllowEmailIntoChannel diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEnrollUser.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEnrollUser.ps1 index ffc9d8ddc652..11345c7922a0 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEnrollUser.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsEnrollUser.ps1 @@ -29,6 +29,7 @@ function Invoke-CIPPStandardTeamsEnrollUser { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'TeamsEnrollUser' -TenantFilter $Tenant -RequiredCapabilities @('MCOSTANDARD', 'MCOEV', 'MCOIMP', 'TEAMS1','Teams_Room_Standard') # Get EnrollUserOverride value using null-coalescing operator $enrollUserOverride = $Settings.EnrollUserOverride.value ?? $Settings.EnrollUserOverride diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalAccessPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalAccessPolicy.ps1 index 0022db523107..6b5e05f56058 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalAccessPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalAccessPolicy.ps1 @@ -30,6 +30,7 @@ function Invoke-CIPPStandardTeamsExternalAccessPolicy { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'TeamsExternalAccessPolicy' -TenantFilter $Tenant -RequiredCapabilities @('MCOSTANDARD', 'MCOEV', 'MCOIMP', 'TEAMS1','Teams_Room_Standard') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsExternalAccessPolicy' $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsExternalAccessPolicy' -CmdParams @{Identity = 'Global' } | Select-Object * diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalFileSharing.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalFileSharing.ps1 index 3230484f898c..b705148469e4 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalFileSharing.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsExternalFileSharing.ps1 @@ -34,6 +34,7 @@ function Invoke-CIPPStandardTeamsExternalFileSharing { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'TeamsExternalFileSharing' -TenantFilter $Tenant -RequiredCapabilities @('MCOSTANDARD', 'MCOEV', 'MCOIMP', 'TEAMS1','Teams_Room_Standard') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsExternalFileSharing' Write-Host "TeamsExternalFileSharing: $($Settings | ConvertTo-Json)" $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsClientConfiguration' | Select-Object AllowGoogleDrive, AllowShareFile, AllowBox, AllowDropBox, AllowEgnyte diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 index d52c75cef036..3857fb601196 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsFederationConfiguration.ps1 @@ -31,6 +31,7 @@ function Invoke-CIPPStandardTeamsFederationConfiguration { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'TeamsFederationConfiguration' -TenantFilter $Tenant -RequiredCapabilities @('MCOSTANDARD', 'MCOEV', 'MCOIMP', 'TEAMS1','Teams_Room_Standard') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsFederationConfiguration' $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTenantFederationConfiguration' -CmdParams @{Identity = 'Global' } | Select-Object * diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 index 7c949243b8d8..e50817a240c0 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGlobalMeetingPolicy.ps1 @@ -34,6 +34,7 @@ function Invoke-CIPPStandardTeamsGlobalMeetingPolicy { ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsGlobalMeetingPolicy' param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'TeamsGlobalMeetingPolicy' -TenantFilter $Tenant -RequiredCapabilities @('MCOSTANDARD', 'MCOEV', 'MCOIMP', 'TEAMS1','Teams_Room_Standard') $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsMeetingPolicy' -CmdParams @{Identity = 'Global' } | Select-Object AllowAnonymousUsersToJoinMeeting, AllowAnonymousUsersToStartMeeting, AutoAdmittedUsers, AllowPSTNUsersToBypassLobby, MeetingChatEnabledType, DesignatedPresenterRoleMode, AllowExternalParticipantGiveRequestControl $MeetingChatEnabledType = $Settings.MeetingChatEnabledType.value ?? $Settings.MeetingChatEnabledType diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGuestAccess.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGuestAccess.ps1 index 715ef12c3386..cf15105b9a3c 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGuestAccess.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsGuestAccess.ps1 @@ -29,6 +29,7 @@ function Invoke-CIPPStandardTeamsGuestAccess { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'TeamsGuestAccess' -TenantFilter $Tenant -RequiredCapabilities @('MCOSTANDARD', 'MCOEV', 'MCOIMP', 'TEAMS1','Teams_Room_Standard') $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsClientConfiguration' -CmdParams @{Identity = 'Global' } | Select-Object AllowGuestUser diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingRecordingExpiration.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingRecordingExpiration.ps1 index bc8cbd0efb89..0fc33957ed41 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingRecordingExpiration.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingRecordingExpiration.ps1 @@ -30,6 +30,7 @@ function Invoke-CIPPStandardTeamsMeetingRecordingExpiration { ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsMeetingRecordingExpiration' param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'TeamsMeetingRecordingExpiration' -TenantFilter $Tenant -RequiredCapabilities @('MCOSTANDARD', 'MCOEV', 'MCOIMP', 'TEAMS1','Teams_Room_Standard') # Input validation $ExpirationDays = try { [int64]$Settings.ExpirationDays } catch { Write-Warning "Invalid ExpirationDays value provided: $($Settings.ExpirationDays)"; return } @@ -73,9 +74,8 @@ function Invoke-CIPPStandardTeamsMeetingRecordingExpiration { if ($Settings.report -eq $true) { Add-CIPPBPAField -FieldName 'TeamsMeetingRecordingExpiration' -FieldValue $CurrentExpirationDays -StoreAs string -Tenant $Tenant - $CurrentExpirationDays = [PSCustomObject]@{ - ExpirationDays = [string]$CurrentExpirationDays - } + $CurrentExpirationDays = if ($StateIsCorrect) { $true } else { $CurrentExpirationDays } + Set-CIPPStandardsCompareField -FieldName 'standards.TeamsMeetingRecordingExpiration' -FieldValue $CurrentExpirationDays -Tenant $Tenant } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingVerification.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingVerification.ps1 index c7938c496d19..f91527604974 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingVerification.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingVerification.ps1 @@ -33,6 +33,7 @@ function Invoke-CIPPStandardTeamsMeetingVerification { ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsMeetingVerification' param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'TeamsMeetingVerification' -TenantFilter $Tenant -RequiredCapabilities @('MCOSTANDARD', 'MCOEV', 'MCOIMP', 'TEAMS1','Teams_Room_Standard') $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsMeetingPolicy' -CmdParams @{Identity = 'Global' } | Select-Object CaptchaVerificationForMeetingJoin $CaptchaVerificationForMeetingJoin = $Settings.CaptchaVerificationForMeetingJoin.value ?? $Settings.CaptchaVerificationForMeetingJoin $StateIsCorrect = ($CurrentState.CaptchaVerificationForMeetingJoin -eq $CaptchaVerificationForMeetingJoin) diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 index 3353d39162a1..c9921642398e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMeetingsByDefault.ps1 @@ -29,6 +29,7 @@ function Invoke-CIPPStandardTeamsMeetingsByDefault { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'TeamsMeetingsByDefault' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsMeetingsByDefault' # Get state value using null-coalescing operator @@ -41,7 +42,7 @@ function Invoke-CIPPStandardTeamsMeetingsByDefault { # Input validation if (([string]::IsNullOrWhiteSpace($state) -or $state -eq 'Select a value') -and ($Settings.remediate -eq $true -or $Settings.alert -eq $true)) { Write-LogMessage -API 'Standards' -tenant $Tenant -message 'TeamsMeetingsByDefault: Invalid state parameter set' -sev Error - Return + return } if ($Settings.remediate -eq $true) { @@ -64,7 +65,7 @@ function Invoke-CIPPStandardTeamsMeetingsByDefault { if ($StateIsCorrect -eq $true) { Write-LogMessage -API 'Standards' -tenant $Tenant -message "The tenant TeamsMeetingsByDefault is set correctly to $state" -sev Info } else { - Write-StandardsAlert -message "The tenant TeamsMeetingsByDefault is not set correctly to $state" -object @{CurrentState = $CurrentState; WantedState = $WantedState} -tenant $Tenant -standardName 'TeamsMeetingsByDefault' -standardId $Settings.standardId + Write-StandardsAlert -message "The tenant TeamsMeetingsByDefault is not set correctly to $state" -object @{CurrentState = $CurrentState; WantedState = $WantedState } -tenant $Tenant -standardName 'TeamsMeetingsByDefault' -standardId $Settings.standardId Write-LogMessage -API 'Standards' -tenant $Tenant -message "The tenant TeamsMeetingsByDefault is not set correctly to $state" -sev Info } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 index a1bf1aa2ad49..f39274fce83b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTeamsMessagingPolicy.ps1 @@ -38,6 +38,7 @@ Function Invoke-CIPPStandardTeamsMessagingPolicy { ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TeamsMessagingPolicy' param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'TeamsMessagingPolicy' -TenantFilter $Tenant -RequiredCapabilities @('MCOSTANDARD', 'MCOEV', 'MCOIMP', 'TEAMS1','Teams_Room_Standard') $CurrentState = New-TeamsRequest -TenantFilter $Tenant -Cmdlet 'Get-CsTeamsMessagingPolicy' -CmdParams @{Identity = 'Global' } if ($null -eq $Settings.AllowOwnerDeleteMessage) { $Settings.AllowOwnerDeleteMessage = $CurrentState.AllowOwnerDeleteMessage } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 index 1365cdc31f75..d7b7180e149b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTenantDefaultTimezone.ps1 @@ -29,6 +29,7 @@ function Invoke-CIPPStandardTenantDefaultTimezone { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'TenantDefaultTimezone' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TenantDefaultTimezone' $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 index 79e154dbe8e0..a9d06c550248 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTransportRuleTemplate.ps1 @@ -26,9 +26,10 @@ function Invoke-CIPPStandardTransportRuleTemplate { https://docs.cipp.app/user-documentation/tenant/standards/list-standards #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'TransportRuleTemplate' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TransportRuleTemplate' - - If ($Settings.remediate -eq $true) { + $existingRules = New-ExoRequest -ErrorAction SilentlyContinue -tenantid $Tenant -cmdlet 'Get-TransportRule' -useSystemMailbox $true + if ($Settings.remediate -eq $true) { Write-Host "Settings: $($Settings | ConvertTo-Json)" $Settings.transportRuleTemplate ? ($Settings | Add-Member -NotePropertyName 'TemplateList' -NotePropertyValue $Settings.transportRuleTemplate) : $null foreach ($Template in $Settings.TemplateList) { @@ -36,8 +37,7 @@ function Invoke-CIPPStandardTransportRuleTemplate { $Table = Get-CippTable -tablename 'templates' $Filter = "PartitionKey eq 'TransportTemplate' and RowKey eq '$($Template.value)'" $RequestParams = (Get-AzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom-Json - $Existing = New-ExoRequest -ErrorAction SilentlyContinue -tenantid $Tenant -cmdlet 'Get-TransportRule' -useSystemMailbox $true | Where-Object -Property Identity -EQ $RequestParams.name - + $Existing = $existingRules | Where-Object -Property Identity -EQ $RequestParams.name try { if ($Existing) { @@ -58,4 +58,21 @@ function Invoke-CIPPStandardTransportRuleTemplate { } } } + if ($Settings.report -eq $true) { + $rules = $Settings.transportRuleTemplate.JSON | ConvertFrom-Json -Depth 10 + $MissingRules = foreach ($rule in $rules) { + $CheckExististing = $existingRules | Where-Object -Property identity -EQ $rule.displayname + if (!$CheckExististing) { + $rule.displayname + } + } + + if ($MissingRules.Count -eq 0) { + $fieldValue = $true + } else { + $fieldValue = $MissingRules -join ', ' + } + + Set-CIPPStandardsCompareField -FieldName 'standards.TransportRuleTemplate' -FieldValue $fieldValue -Tenant $Tenant + } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTwoClickEmailProtection.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTwoClickEmailProtection.ps1 index 13cbb9562d82..29a8c8ce6267 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTwoClickEmailProtection.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardTwoClickEmailProtection.ps1 @@ -29,6 +29,7 @@ function Invoke-CIPPStandardTwoClickEmailProtection { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'TwoClickEmailProtection' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'TwoClickEmailProtection' # Get state value using null-coalescing operator diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 index e1c2ee7ca8ac..75f1036c7d8f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 @@ -30,6 +30,7 @@ function Invoke-CIPPStandardUserSubmissions { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'UserSubmissions' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'UserSubmissions' # Get state value using null-coalescing operator diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 index 11f3f95605db..d40860653b59 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardcalDefault.ps1 @@ -32,6 +32,7 @@ function Invoke-CIPPStandardcalDefault { param($Tenant, $Settings, $QueueItem) ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'calDefault' + Test-CIPPStandardLicense -StandardName 'calDefault' -TenantFilter $Tenant -RequiredCapabilities @('EXCHANGE_S_STANDARD', 'EXCHANGE_S_ENTERPRISE', 'EXCHANGE_LITE') #No Foundation because that does not allow powershell access # Get permissionLevel value using null-coalescing operator $permissionLevel = $Settings.permissionLevel.value ?? $Settings.permissionLevel @@ -39,10 +40,10 @@ function Invoke-CIPPStandardcalDefault { # 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 - Return + return } - If ($Settings.remediate -eq $true) { + if ($Settings.remediate -eq $true) { $Mailboxes = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-Mailbox' | Sort-Object UserPrincipalName $TotalMailboxes = $Mailboxes.Count Write-LogMessage -API 'Standards' -tenant $Tenant -message "Started setting default calendar permissions for $($TotalMailboxes) mailboxes." -sev Info @@ -67,44 +68,48 @@ function Invoke-CIPPStandardcalDefault { $Mailbox = $_ try { New-ExoRequest -tenantid $Tenant -cmdlet 'Get-MailboxFolderStatistics' -cmdParams @{identity = $Mailbox.UserPrincipalName; FolderScope = 'Calendar' } -Anchor $Mailbox.UserPrincipalName | Where-Object { $_.FolderType -eq 'Calendar' } | - ForEach-Object { - try { - New-ExoRequest -tenantid $Tenant -cmdlet 'Set-MailboxFolderPermission' -cmdParams @{Identity = "$($Mailbox.UserPrincipalName):$($_.FolderId)"; User = 'Default'; AccessRights = $permissionLevel } -Anchor $Mailbox.UserPrincipalName - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Set default folder permission for $($Mailbox.UserPrincipalName):\$($_.Name) to $permissionLevel" -sev Debug - $SuccessCounter++ - } catch { - $ErrorMessage = Get-CippException -Exception $_ - Write-Host "Setting cal failed: $ErrorMessage" - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Could not set default calendar permissions for $($Mailbox.UserPrincipalName). Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage - } + ForEach-Object { + try { + New-ExoRequest -tenantid $Tenant -cmdlet 'Set-MailboxFolderPermission' -cmdParams @{Identity = "$($Mailbox.UserPrincipalName):$($_.FolderId)"; User = 'Default'; AccessRights = $permissionLevel } -Anchor $Mailbox.UserPrincipalName + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Set default folder permission for $($Mailbox.UserPrincipalName):\$($_.Name) to $permissionLevel" -sev Debug + $SuccessCounter++ + } catch { + $ErrorMessage = Get-CippException -Exception $_ + Write-Host "Setting cal failed: $ErrorMessage" + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Could not set default calendar permissions for $($Mailbox.UserPrincipalName). Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage } - } catch { - $ErrorMessage = Get-CippException -Exception $_ - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Could not set default calendar permissions for $($Mailbox.UserPrincipalName). Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage - } - $processedMailboxes++ - if ($processedMailboxes % 25 -eq 0) { - $LastRun = @{ - RowKey = 'calDefaults' - PartitionKey = $Tenant - totalMailboxes = $TotalMailboxes - processedMailboxes = $processedMailboxes - currentSuccessCount = $SuccessCounter - } - Add-CIPPAzDataTableEntity @LastRunTable -Entity $LastRun -Force - Write-Host "Processed $processedMailboxes mailboxes" } + } catch { + $ErrorMessage = Get-CippException -Exception $_ + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Could not set default calendar permissions for $($Mailbox.UserPrincipalName). Error: $($ErrorMessage.NormalizedError)" -sev Error -LogData $ErrorMessage } - - $LastRun = @{ - RowKey = 'calDefaults' - PartitionKey = $Tenant - totalMailboxes = $TotalMailboxes - processedMailboxes = $processedMailboxes - currentSuccessCount = $SuccessCounter + $processedMailboxes++ + if ($processedMailboxes % 25 -eq 0) { + $LastRun = @{ + RowKey = 'calDefaults' + PartitionKey = $Tenant + totalMailboxes = $TotalMailboxes + processedMailboxes = $processedMailboxes + currentSuccessCount = $SuccessCounter + } + Add-CIPPAzDataTableEntity @LastRunTable -Entity $LastRun -Force + Write-Host "Processed $processedMailboxes mailboxes" } - Add-CIPPAzDataTableEntity @LastRunTable -Entity $LastRun -Force + } - Write-LogMessage -API 'Standards' -tenant $Tenant -message "Successfully set default calendar permissions for $SuccessCounter out of $TotalMailboxes mailboxes." -sev Info + $LastRun = @{ + RowKey = 'calDefaults' + PartitionKey = $Tenant + totalMailboxes = $TotalMailboxes + processedMailboxes = $processedMailboxes + currentSuccessCount = $SuccessCounter } + Add-CIPPAzDataTableEntity @LastRunTable -Entity $LastRun -Force + + Write-LogMessage -API 'Standards' -tenant $Tenant -message "Successfully set default calendar permissions for $SuccessCounter out of $TotalMailboxes mailboxes." -sev Info + } + if ($Settings.report -eq $true) { + #This script always returns true, as it only disables the Safe Senders list + Set-CIPPStandardsCompareField -FieldName 'standards.SafeSendersDisable' -FieldValue $true -Tenant $Tenant } +} diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 index 6f3c1f886b16..68c3632a8abe 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandarddisableMacSync.ps1 @@ -28,6 +28,7 @@ function Invoke-CIPPStandarddisableMacSync { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'disableMacSync' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'disableMacSync' $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneBrandingProfile.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneBrandingProfile.ps1 index cc0cb204840a..f9c01147a142 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneBrandingProfile.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneBrandingProfile.ps1 @@ -38,6 +38,7 @@ function Invoke-CIPPStandardintuneBrandingProfile { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'intuneBrandingProfile' -TenantFilter $Tenant -RequiredCapabilities @('INTUNE_A', 'MDM_Services', 'EMS', 'SCCM', 'MICROSOFTINTUNEPLAN1') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'intuneBrandingProfile' $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/deviceManagement/intuneBrandingProfiles/c3a59481-1bf2-46ce-94b3-66eec07a8d60' -tenantid $Tenant -AsApp $true diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 index eb9e1693da54..7855d7a4295e 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceReg.ps1 @@ -29,6 +29,7 @@ function Invoke-CIPPStandardintuneDeviceReg { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'intuneDeviceReg' -TenantFilter $Tenant -RequiredCapabilities @('INTUNE_A', 'MDM_Services', 'EMS', 'SCCM', 'MICROSOFTINTUNEPLAN1') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'intuneDeviceReg' $PreviousSetting = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/policies/deviceRegistrationPolicy' -tenantid $Tenant diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 index 07d19f264bdf..4339901ed20d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneDeviceRetirementDays.ps1 @@ -30,19 +30,26 @@ function Invoke-CIPPStandardintuneDeviceRetirementDays { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'intuneDeviceRetirementDays' -TenantFilter $Tenant -RequiredCapabilities @('INTUNE_A', 'MDM_Services', 'EMS', 'SCCM', 'MICROSOFTINTUNEPLAN1') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'intuneDeviceRetirementDays' - $CurrentInfo = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/deviceManagement/managedDeviceCleanupSettings' -tenantid $Tenant) + $CurrentInfo = (New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/deviceManagement/managedDeviceCleanupRules' -tenantid $Tenant) $StateIsCorrect = if ($CurrentInfo.DeviceInactivityBeforeRetirementInDays -eq $Settings.days) { $true } else { $false } - If ($Settings.remediate -eq $true) { + if ($Settings.remediate -eq $true) { if ($CurrentInfo.DeviceInactivityBeforeRetirementInDays -eq $Settings.days) { Write-LogMessage -API 'Standards' -tenant $tenant -message "DeviceInactivityBeforeRetirementInDays for $($Settings.days) days is already enabled." -sev Info } else { + if ($CurrentInfo) { + $Type = 'Patch' + $id = "('$($CurrentInfo.id)')" + } else { + $Type = 'Post' + } try { - $body = @{ DeviceInactivityBeforeRetirementInDays = $Settings.days } | ConvertTo-Json - (New-GraphPostRequest -tenantid $tenant -Uri 'https://graph.microsoft.com/beta/deviceManagement/managedDeviceCleanupSettings' -Type PATCH -Body $body -ContentType 'application/json') + $body = '{"displayName":"Default Policy","description":"Default Policy","deviceCleanupRulePlatformType":"all","deviceInactivityBeforeRetirementInDays":' + $Settings.days + '}' + (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/deviceManagement/managedDeviceCleanupRules$id" -Type $Type -Body $body -ContentType 'application/json') Write-LogMessage -API 'Standards' -tenant $tenant -message "Enabled DeviceInactivityBeforeRetirementInDays for $($Settings.days) days." -sev Info } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 index 43a5da1d2d24..d10df96a7fd5 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardintuneRequireMFA.ps1 @@ -27,6 +27,7 @@ function Invoke-CIPPStandardintuneRequireMFA { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'intuneRequireMFA' -TenantFilter $Tenant -RequiredCapabilities @('INTUNE_A', 'MDM_Services', 'EMS', 'SCCM', 'MICROSOFTINTUNEPLAN1') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'intuneRequireMFA' $PreviousSetting = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/policies/deviceRegistrationPolicy' -tenantid $Tenant diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 index c65bf679b010..74db530e5158 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingCapability.ps1 @@ -32,6 +32,7 @@ function Invoke-CIPPStandardsharingCapability { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'sharingCapability' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') $CurrentInfo = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingDomainRestriction.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingDomainRestriction.ps1 index 3fa2f071bda4..11d4313f5504 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingDomainRestriction.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardsharingDomainRestriction.ps1 @@ -31,6 +31,7 @@ function Invoke-CIPPStandardsharingDomainRestriction { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'sharingDomainRestriction' -TenantFilter $Tenant -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') $CurrentState = New-GraphGetRequest -Uri 'https://graph.microsoft.com/beta/admin/sharepoint/settings' -tenantid $Tenant -AsApp $true diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardunmanagedSync.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardunmanagedSync.ps1 index 57fe9a533670..651a5c22ca85 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardunmanagedSync.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardunmanagedSync.ps1 @@ -30,6 +30,7 @@ function Invoke-CIPPStandardunmanagedSync { #> param($Tenant, $Settings) + Test-CIPPStandardLicense -StandardName 'unmanagedSync' -TenantFilter $Tenant -RequiredCapabilities @('INTUNE_A', 'MDM_Services', 'EMS', 'SCCM', 'MICROSOFTINTUNEPLAN1') ##$Rerun -Type Standard -Tenant $Tenant -Settings $Settings 'unmanagedSync' $CurrentState = Get-CIPPSPOTenant -TenantFilter $Tenant | Select-Object _ObjectIdentity_, TenantFilter, ConditionalAccessPolicy @@ -38,7 +39,7 @@ function Invoke-CIPPStandardunmanagedSync { $Label = $Settings.state.label ?? 'Block Access' # Default label if not set, for pre v8.0.3 standard compatibility $StateIsCorrect = ($CurrentState.ConditionalAccessPolicy -eq $WantedState) - If ($Settings.remediate -eq $true) { + if ($Settings.remediate -eq $true) { if ($StateIsCorrect -eq $true) { Write-LogMessage -API 'Standards' -tenant $Tenant -message "Sync for unmanaged devices is already correctly set to: $Label" -sev Info diff --git a/Modules/CIPPCore/Public/Test-CIPPAccessTenant.ps1 b/Modules/CIPPCore/Public/Test-CIPPAccessTenant.ps1 index bae5f70793b0..561568426189 100644 --- a/Modules/CIPPCore/Public/Test-CIPPAccessTenant.ps1 +++ b/Modules/CIPPCore/Public/Test-CIPPAccessTenant.ps1 @@ -106,7 +106,7 @@ function Test-CIPPAccessTenant { try { $null = New-ExoRequest -tenantid $Tenant.customerId -cmdlet 'Get-OrganizationConfig' -ErrorAction Stop - $OrgManagementRoles = New-ExoRequest -tenantid $Tenant.customerId -cmdlet 'Get-ManagementRoleAssignment' -cmdParams @{ RoleAssignee = 'Organization Management'; Delegating = $false } | Select-Object -Property Role, Guid + $OrgManagementRoles = New-ExoRequest -tenantid $Tenant.customerId -cmdlet 'Get-ManagementRoleAssignment' -cmdParams @{ Delegating = $false } | Where-Object { $_.RoleAssigneeName -eq 'Organization Management' } | Select-Object -Property Role, Guid Write-Information "Found $($OrgManagementRoles.Count) Organization Management roles in Exchange" $Results.OrgManagementRoles = $OrgManagementRoles diff --git a/Modules/CIPPCore/Public/Webhooks/Invoke-CIPPWebhookProcessing.ps1 b/Modules/CIPPCore/Public/Webhooks/Invoke-CIPPWebhookProcessing.ps1 index 42adae4b24de..b7361fe4b2ea 100644 --- a/Modules/CIPPCore/Public/Webhooks/Invoke-CIPPWebhookProcessing.ps1 +++ b/Modules/CIPPCore/Public/Webhooks/Invoke-CIPPWebhookProcessing.ps1 @@ -19,42 +19,58 @@ function Invoke-CippWebhookProcessing { } $Tenant = Get-Tenants -IncludeErrors | Where-Object { $_.defaultDomainName -eq $TenantFilter } - Write-Host "Received data. Our Action List is $($data.CIPPAction)" + Write-Host "Received data. Our Action List is $($Data.CIPPAction)" - $ActionList = ($data.CIPPAction | ConvertFrom-Json -ErrorAction SilentlyContinue).value + $ActionList = ($Data.CIPPAction | ConvertFrom-Json -ErrorAction SilentlyContinue).value $ActionResults = foreach ($action in $ActionList) { Write-Host "this is our action: $($action | ConvertTo-Json -Depth 15 -Compress)" switch ($action) { 'disableUser' { - Set-CIPPSignInState -TenantFilter $TenantFilter -User $data.UserId -AccountEnabled $false -APIName 'Alert Engine' -Headers 'Alert Engine' + try { + Set-CIPPSignInState -TenantFilter $TenantFilter -User $Data.UserId -AccountEnabled $false -APIName 'Alert Engine' -Headers 'Alert Engine' + } catch { + Write-Host "Failed to disable user $($Data.UserId)`: $($_.Exception.Message)" + } } 'becremediate' { - $username = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($data.UserId)" -tenantid $TenantFilter).UserPrincipalName - Set-CIPPResetPassword -UserID $username -tenantFilter $TenantFilter -APIName 'Alert Engine' -Headers 'Alert Engine' - Set-CIPPSignInState -userid $username -AccountEnabled $false -tenantFilter $TenantFilter -APIName 'Alert Engine' -Headers 'Alert Engine' - Revoke-CIPPSessions -userid $username -username $username -Headers 'Alert Engine' -APIName 'Alert Engine' -tenantFilter $TenantFilter + $Username = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($Data.UserId)" -tenantid $TenantFilter).UserPrincipalName + try { + Set-CIPPResetPassword -UserID $Username -tenantFilter $TenantFilter -APIName 'Alert Engine' -Headers 'Alert Engine' + } catch { + Write-Host "Failed to reset password for $Username`: $($_.Exception.Message)" + } + try { + Set-CIPPSignInState -userid $Username -AccountEnabled $false -tenantFilter $TenantFilter -APIName 'Alert Engine' -Headers 'Alert Engine' + } catch { + Write-Host "Failed to disable sign-in for $Username`: $($_.Exception.Message)" + } + try { + Revoke-CIPPSessions -userid $Username -username $Username -Headers 'Alert Engine' -APIName 'Alert Engine' -tenantFilter $TenantFilter + } catch { + Write-Host "Failed to revoke sessions for $Username`: $($_.Exception.Message)" + } $RuleDisabled = 0 - New-ExoRequest -anchor $username -tenantid $TenantFilter -cmdlet 'Get-InboxRule' -cmdParams @{Mailbox = $username; IncludeHidden = $true } | Where-Object { $_.Name -ne 'Junk E-Mail Rule' -and $_.Name -notlike 'Microsoft.Exchange.OOF.*' } | ForEach-Object { - $null = New-ExoRequest -anchor $username -tenantid $TenantFilter -cmdlet 'Disable-InboxRule' -cmdParams @{Confirm = $false; Identity = $_.Identity } - "Disabled Inbox Rule $($_.Identity) for $username" + New-ExoRequest -anchor $Username -tenantid $TenantFilter -cmdlet 'Get-InboxRule' -cmdParams @{Mailbox = $Username; IncludeHidden = $true } | Where-Object { $_.Name -ne 'Junk E-Mail Rule' -and $_.Name -notlike 'Microsoft.Exchange.OOF.*' } | ForEach-Object { + $null = New-ExoRequest -anchor $Username -tenantid $TenantFilter -cmdlet 'Disable-InboxRule' -cmdParams @{Confirm = $false; Identity = $_.Identity } + "Disabled Inbox Rule $($_.Identity) for $Username" $RuleDisabled++ } if ($RuleDisabled) { - "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." } - "Completed BEC Remediate for $username" - Write-LogMessage -API 'BECRemediate' -tenant $tenantfilter -message "Executed Remediation for $username" -sev 'Info' + "Completed BEC Remediate for $Username" + Write-LogMessage -API 'BECRemediate' -tenant $tenantfilter -message "Executed Remediation for $Username" -sev 'Info' } 'cippcommand' { $CommandSplat = @{} $action.parameters.psobject.properties | ForEach-Object { $CommandSplat.Add($_.name, $_.value) } - if ($CommandSplat['userid']) { $CommandSplat['userid'] = $data.userid } - if ($CommandSplat['tenantfilter']) { $CommandSplat['tenantfilter'] = $tenantfilter } - if ($CommandSplat['tenant']) { $CommandSplat['tenant'] = $tenantfilter } - if ($CommandSplat['user']) { $CommandSplat['user'] = $data.userid } - if ($CommandSplat['username']) { $CommandSplat['username'] = $data.userid } + if ($CommandSplat['userid']) { $CommandSplat['userid'] = $Data.UserId } + if ($CommandSplat['tenantfilter']) { $CommandSplat['tenantfilter'] = $TenantFilter } + if ($CommandSplat['tenant']) { $CommandSplat['tenant'] = $TenantFilter } + if ($CommandSplat['user']) { $CommandSplat['user'] = $Data.UserId } + if ($CommandSplat['username']) { $CommandSplat['username'] = $Data.UserId } & $action.command.value @CommandSplat } } @@ -69,7 +85,7 @@ function Invoke-CippWebhookProcessing { ActionUrl = $GenerateJSON.ButtonUrl ActionText = $GenerateJSON.ButtonText RawData = $Data - IP = $data.ClientIP + IP = $Data.ClientIP PotentialLocationInfo = $LocationInfo ActionsTaken = $ActionResults AuditRecord = $AuditRecord diff --git a/Modules/CippExtensions/ConversionTable.csv b/Modules/CippExtensions/ConversionTable.csv index 704f7c507d5f..5b7cea1f09ea 100644 --- a/Modules/CippExtensions/ConversionTable.csv +++ b/Modules/CippExtensions/ConversionTable.csv @@ -20,6 +20,7 @@ Clipchamp Premium,Clipchamp_Premium,0fe440c5-f2bf-442b-a4f4-9a7af77a200b,ONEDRIV Clipchamp Standard,Clipchamp_Standard,481f3bc2-5756-4b28-9375-5c8c86b99e6b,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Clipchamp Standard,Clipchamp_Standard,481f3bc2-5756-4b28-9375-5c8c86b99e6b,CLIPCHAMP,a1ace008-72f3-4ea0-8dac-33b3a23a2472,Microsoft Clipchamp Clipchamp Standard,Clipchamp_Standard,481f3bc2-5756-4b28-9375-5c8c86b99e6b,ONEDRIVECLIPCHAMP,f7e5b77d-f293-410a-bae8-f941f19fe680,OneDrive for Business (Clipchamp) +Clipchamp Premium Add-on,Clipchamp_Premium_Add_on,4b2c20e4-939d-4bf4-9dd8-6870240cfe19,CLIPCHAMP_PREMIUM,430b908f-78e1-4812-b045-cf83320e7d5d,Microsoft Clipchamp Premium Microsoft 365 Audio Conferencing,MCOMEETADV,0c266dff-15dd-4b49-8397-2bb16070ed52,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing Microsoft Entra ID Basic,AAD_BASIC,2b9c8e7c-319c-43a2-a2a0-48c5c6161de7,AAD_BASIC,c4da7f8a-5ee2-4c99-a7e1-87d2df57f6fe,Microsoft Entra BASIC Microsoft Entra ID P1,AAD_PREMIUM,078d2b04-f1bd-4111-bbd4-b4b1b354cef4,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 @@ -418,6 +419,13 @@ Dynamics 365 Guides vTrial,Dynamics_365_Guides_vTrial,99cb3f83-fbec-4aa1-8262-96 Dynamics 365 Guides vTrial,Dynamics_365_Guides_vTrial,99cb3f83-fbec-4aa1-8262-9679e6df7c53,DYN365_CDS_VIRAL,17ab22cd-a0b3-4536-910a-cb6eb12696c0,Common Data Service Dynamics 365 Guides vTrial,Dynamics_365_Guides_vTrial,99cb3f83-fbec-4aa1-8262-9679e6df7c53,POWER_APPS_DYN365_VIRAL_TRIAL_MIXED_REALITY,066e2fd1-ba15-40e7-aa96-d6636b1cdf71,Power Apps for Dynamics 365 Mixed Reality Dynamics 365 Guides vTrial,Dynamics_365_Guides_vTrial,99cb3f83-fbec-4aa1-8262-9679e6df7c53,POWER_AUTOMATE_DYN365_VIRAL_TRIAL_MIXED_REALITY,26fa8a18-2812-4b3d-96b4-864818ce26be,Power Automate for Dynamics 365 Mixed Reality +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,Forms_Pro_Talent,1c4ae475-5608-43fa-b3f7-d20e07cf24b4,Microsoft Dynamics 365 Customer Voice for Talent +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,D365_HR_SELF_SERVICE_OPS,835b837b-63c1-410e-bf6b-bdef201ad129,Dynamics 365 Human Resource Self Service +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,D365_HR_OPS,8b21a5dc-5485-49ed-a2d4-0e772c830f6d,Dynamics 365 Human Resources +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,D365_HR_Attach,3219525a-4064-45ec-9c35-a33ea6b39a49,Dynamics 365 Human Resources Attach +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,D365_HR_ATTACH_OPS,90d8cb62-e98a-4639-8342-8c7d2c8215ba,Dynamics 365 Human Resources Attach License +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 Hybrid Connector,CRM_HYBRIDCONNECTOR,de176c31-616d-4eae-829a-718918d7ec23,CRM_HYBRIDCONNECTOR,0210d5c8-49d2-4dd1-a01b-a91c7c14e0bf,CRM Hybrid Connector Dynamics 365 Hybrid Connector,CRM_HYBRIDCONNECTOR,de176c31-616d-4eae-829a-718918d7ec23,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 for Marketing Additional Application,DYN365_MARKETING_APPLICATION_ADDON,99c5688b-6c75-4496-876f-07f0fbd69add,DYN365_MARKETING_APPLICATION_ADDON,51cf0638-4861-40c0-8b20-1161ab2f80be,Dynamics 365 for Marketing Additional Application @@ -967,111 +975,129 @@ Microsoft 365 A3 - Unattended License for students use benefit,M365EDU_A3_STUUSE Microsoft 365 A3 - Unattended License for students use benefit,M365EDU_A3_STUUSEBNFT_RPA1,1aa94593-ca12-4254-a738-81a5972958e8,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune for Education Microsoft 365 A3 - Unattended License for students use benefit,M365EDU_A3_STUUSEBNFT_RPA1,1aa94593-ca12-4254-a738-81a5972958e8,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 Microsoft 365 A3 - Unattended License for students use benefit,M365EDU_A3_STUUSEBNFT_RPA1,1aa94593-ca12-4254-a738-81a5972958e8,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CDS_O365_P3,afa73018-811e-46e9-988f-f75d2b1b8430,Common Data Service for Teams -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,LOCKBOX_ENTERPRISE,9f431833-0334-42de-a7dc-70aa40db46db,Customer Lockbox -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_Exchange,cd31b152-6326-4d1b-ae1b-997b625182e6,Data Classification in Microsoft 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCHANGE_S_ENTERPRISE,efb87545-963c-4e0d-99df-69c6916d9eb0,Exchange Online (Plan 2) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Content_Explorer,d9fa6af4-e046-4c89-9226-729a0786685d,Information Protection and Governance Analytics - Premium -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ContentExplorer_Standard,2b815d45-56e4-4e3a-b65c-66cb9175b560,Information Protection and Governance Analytics – Standard -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_CLP2,efb0351d-3b08-4503-993d-383af8de41e3,Information Protection for Office 365 - Premium -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_CLP1,5136a095-5cf0-4aff-bec3-e84448b38ea5,Information Protection for Office 365 - Standard -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,M365_ADVANCED_AUDITING,2f442157-a11c-46b9-ae5b-6e39ff4e5849,Microsoft 365 Advanced Auditing -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,OFFICESUBSCRIPTION,43de0ff5-c92c-492b-9116-175376d08c38,Microsoft 365 Apps for Enterprise -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_COMMUNICATION_COMPLIANCE,a413a9ff-720c-4822-98ef-2f37c2a21f4c,Microsoft 365 Communication Compliance -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MTP,bf28f719-7844-4079-9c78-c1307898e192,Microsoft 365 Defender -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFTBOOKINGS,199a5c09-e0ca-4e37-8f7c-b05d533e1ea2,Microsoft Bookings -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMUNICATIONS_DLP,6dc145d6-95dd-4191-b9c3-185575ee6f6b,Microsoft Communications DLP -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CUSTOMER_KEY,6db1f1db-2b46-403f-be40-e39395f08dbb,Microsoft Customer Key -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,DATA_INVESTIGATIONS,46129a58-a698-46f0-aa5b-17f6586297d9,Microsoft Data Investigations -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ATP_ENTERPRISE,f20fedf3-f3c3-43c3-8267-2bfdd51c0939,Microsoft Defender for Office 365 (Plan 1) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,THREAT_INTELLIGENCE,8e0c0a52-6a6c-4d40-8370-dd62790dcd70,Microsoft Defender for Office 365 (Plan 2) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCEL_PREMIUM,531ee2f8-b1cb-453b-9c21-d2180d014ca5,Microsoft Excel Advanced Analytics -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,OFFICE_FORMS_PLAN_3,96c1e14a-ef43-418d-b115-9636cdaa8eed,Microsoft Forms (Plan 3) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INFO_GOVERNANCE,e26c2fcc-ab91-4a61-b35c-03cdc8dddf66,Microsoft Information Governance -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INSIDER_RISK,d587c7a3-bda9-4f99-8776-9bcf59c84f75,Microsoft Insider Risk Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,KAIZALA_STANDALONE,0898bdbb-73b0-471a-81e5-20f1fe4dd66e,Microsoft Kaizala Pro -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ML_CLASSIFICATION,d2d51368-76c9-4317-ada2-a12c004c432f,Microsoft ML-Based Classification -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCHANGE_ANALYTICS,34c0d7a0-a70f-4668-9238-47f9fc208882,Microsoft MyAnalytics (Full) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RECORDS_MANAGEMENT,65cc641f-cccd-4643-97e0-a17e3045e541,Microsoft Records Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_SEARCH,94065c59-bc8e-4e8b-89e5-5138d471eaff,Microsoft Search -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Deskless,8c7d2df8-86f0-4902-b2ed-a0458298f3b3,Microsoft StaffHub -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,STREAM_O365_E5,6c6042f5-6f01-4d67-b8c1-eb99d36eed3e,Microsoft Stream for Office 365 E5 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,TEAMS1,57ff2da0-773e-42df-b2af-ffb7a2317929,Microsoft Teams -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MINECRAFT_EDUCATION_EDITION,4c246bbc-f513-4311-beff-eba54c353256,Minecraft Education Edition -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_O365,882e1d05-acd1-4ccb-8708-6ee03664b117,Mobile Device Management for Office 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Nucleus,db4d623d-b514-490b-b7ef-8885eee514de,Nucleus -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EQUIVIO_ANALYTICS,4de31727-a228-4ec3-a5bf-8e45b5ca48cc,Office 365 Advanced eDiscovery -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ADALLOM_S_O365,8c098270-9dd4-4350-9b30-ba4703f3b36b,Office 365 Cloud App Security -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PAM_ENTERPRISE,b1188c4c-1b36-4018-b48b-ee07604f6feb,Office 365 Privileged Access Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SAFEDOCS,bf6f5520-59e3-4f82-974b-7dbbc4fd27c7,Office 365 SafeDocs -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SHAREPOINTWAC_EDU,e03c7e47-402c-463c-ab25-949079bedb21,Office for the Web for Education -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,POWERAPPS_O365_P3,9c0dab89-a30c-4117-86e7-97bda240acd2,Power Apps for Office 365 (Plan 3) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,BI_AZURE_P2,70d33638-9c74-4d01-bfd3-562de28bd4ba,Power BI Pro -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PREMIUM_ENCRYPTION,617b097b-4b93-4ede-83de-5f075bb5fb2f,Premium Encryption in Office 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PROJECT_O365_P3,b21a6b06-1988-436e-a07b-51ec6d9f52ad,Project for Office (Plan E5) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMUNICATIONS_COMPLIANCE,41fcdd7d-4733-4863-9cf4-c65b83ce2df4,Microsoft Communications Compliance -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INSIDER_RISK_MANAGEMENT,9d0c4ee5-e4a1-4625-ab39-d82b619b1a34,Microsoft Insider Risk Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SCHOOL_DATA_SYNC_P2,500b6a2a-7a50-4f40-b5f9-160e5b8c2f48,School Data Sync (Plan 2) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SHAREPOINTENTERPRISE_EDU,63038b2c-28d0-45f6-bc36-33062963b498,SharePoint (Plan 2) for Education -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SWAY,a23b959c-7ce8-4e57-9140-b90eb88a9e97,Sway -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,BPOS_S_TODO_3,3fb82609-8c27-4f7b-bd51-30634711ee67,To-Do (Plan 3) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,VIVA_LEARNING_SEEDED,b76fb638-6ba6-402a-b9f9-83d28acb3d86,Viva Learning Seeded -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WHITEBOARD_PLAN3,4a51bca5-1eff-43f5-878c-177680f191af,Whiteboard (Plan 3) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WINDEFATP,871d91ec-ec1a-452b-a83f-bd76c7d770ef,Microsoft Defender for Endpoint -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFTENDPOINTDLP,64bfac92-2b17-4482-b5e5-a0304429de3e,Microsoft Endpoint DLP -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,UNIVERSAL_PRINT_01,795f6fe0-cc4d-4773-b050-5dde4dc704c9,Universal Print -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Virtualization Rights for Windows 10 (E3/E5+VDA),e7c91390-7625-45be-94e0-e16907e03118,Windows 10/11 Enterprise -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WINDOWSUPDATEFORBUSINESS_DEPLOYMENTSERVICE,7bf960f6-2cd9-443a-8046-5dbff9558365,Windows Update for Business Deployment Service -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_PREMIUM_P2,eec0eb4f-6444-4f95-aba0-50c24d67f998,Microsoft Entra ID P2 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_PREMIUM,6c57d4b6-3b23-47a5-9bc9-69f17b4947b3,Azure Information Protection Premium P1 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_PREMIUM2,5689bec4-755d-4753-8b61-40975025187c,Azure Information Protection Premium P2 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,DYN365_CDS_O365_P3,28b0fa46-c39a-4188-89e2-58e979a6b014,Common Data Service -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MFA_PREMIUM,8a256a2b-b617-496d-b51b-e76466e88db0,Microsoft Azure Multi-Factor Authentication -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ADALLOM_S_STANDALONE,2e2ddb96-6af9-4b1d-a3f0-d6ecfd22edb2,Microsoft Defender for Cloud Apps -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ATA,14ab5db5-e6c4-4b20-b4bc-13e36fd2227f,Microsoft Defender for Identity -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune for Education -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,FLOW_O365_P3,07699545-9485-468e-95b6-2fca3738be01,Power Automate for Office 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,POWER_VIRTUAL_AGENTS_O365_P3,ded3d325-1bdc-453e-8432-5bac26d7a014,Power Virtual Agents for Office 365 -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CDS_O365_P3,afa73018-811e-46e9-988f-f75d2b1b8430,Common Data Service for Teams +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,LOCKBOX_ENTERPRISE,9f431833-0334-42de-a7dc-70aa40db46db,Customer Lockbox +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CustomerLockboxA_Enterprise,3ec18638-bd4c-4d3b-8905-479ed636b83e,Customer Lockbox (A) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_Exchange,cd31b152-6326-4d1b-ae1b-997b625182e6,Data Classification in Microsoft 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMON_DEFENDER_PLATFORM_FOR_OFFICE,a312bdeb-1e21-40d0-84b1-0e73f128144f,Defender Platform for Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCHANGE_S_ENTERPRISE,efb87545-963c-4e0d-99df-69c6916d9eb0,Exchange Online (Plan 2) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,GRAPH_CONNECTORS_SEARCH_INDEX,a6520331-d7d4-4276-95f5-15c0933bc757,Graph Connectors Search with Index +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Content_Explorer,d9fa6af4-e046-4c89-9226-729a0786685d,Information Protection and Governance Analytics - Premium +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ContentExplorer_Standard,2b815d45-56e4-4e3a-b65c-66cb9175b560,Information Protection and Governance Analytics – Standard +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_CLP2,efb0351d-3b08-4503-993d-383af8de41e3,Information Protection for Office 365 - Premium +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_CLP1,5136a095-5cf0-4aff-bec3-e84448b38ea5,Information Protection for Office 365 - Standard +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,M365_ADVANCED_AUDITING,2f442157-a11c-46b9-ae5b-6e39ff4e5849,Microsoft 365 Advanced Auditing +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,OFFICESUBSCRIPTION,43de0ff5-c92c-492b-9116-175376d08c38,Microsoft 365 Apps for enterprise +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,M365_AUDIT_PLATFORM,f6de4823-28fa-440b-b886-4783fa86ddba,Microsoft 365 Audit Platform +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_COMMUNICATION_COMPLIANCE,a413a9ff-720c-4822-98ef-2f37c2a21f4c,Microsoft 365 Communication Compliance +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MTP,bf28f719-7844-4079-9c78-c1307898e192,Microsoft 365 Defender +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFTBOOKINGS,199a5c09-e0ca-4e37-8f7c-b05d533e1ea2,Microsoft Bookings +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CLIPCHAMP,a1ace008-72f3-4ea0-8dac-33b3a23a2472,Microsoft Clipchamp +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMUNICATIONS_DLP,6dc145d6-95dd-4191-b9c3-185575ee6f6b,Microsoft Communications DLP +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CUSTOMER_KEY,6db1f1db-2b46-403f-be40-e39395f08dbb,Microsoft Customer Key +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ATP_ENTERPRISE,f20fedf3-f3c3-43c3-8267-2bfdd51c0939,Microsoft Defender for Office 365 (Plan 1) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,THREAT_INTELLIGENCE,8e0c0a52-6a6c-4d40-8370-dd62790dcd70,Microsoft Defender for Office 365 (Plan 2) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCEL_PREMIUM,531ee2f8-b1cb-453b-9c21-d2180d014ca5,Microsoft Excel Advanced Analytics +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,OFFICE_FORMS_PLAN_3,96c1e14a-ef43-418d-b115-9636cdaa8eed,Microsoft Forms (Plan 3) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INFO_GOVERNANCE,e26c2fcc-ab91-4a61-b35c-03cdc8dddf66,Microsoft Information Governance +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INSIDER_RISK,d587c7a3-bda9-4f99-8776-9bcf59c84f75,Microsoft Insider Risk Management +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INSIDER_RISK_MANAGEMENT,9d0c4ee5-e4a1-4625-ab39-d82b619b1a34,Microsoft Insider Risk Management - Exchange +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,KAIZALA_STANDALONE,0898bdbb-73b0-471a-81e5-20f1fe4dd66e,Microsoft Kaizala Pro +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_LOOP,c4b8c31a-fb44-4c65-9837-a21f55fcabda,Microsoft Loop +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ML_CLASSIFICATION,d2d51368-76c9-4317-ada2-a12c004c432f,Microsoft ML-Based Classification +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCHANGE_ANALYTICS,34c0d7a0-a70f-4668-9238-47f9fc208882,Microsoft MyAnalytics (Full) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RECORDS_MANAGEMENT,65cc641f-cccd-4643-97e0-a17e3045e541,Microsoft Records Management +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_SEARCH,94065c59-bc8e-4e8b-89e5-5138d471eaff,Microsoft Search +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Deskless,8c7d2df8-86f0-4902-b2ed-a0458298f3b3,Microsoft StaffHub +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,STREAM_O365_E5,6c6042f5-6f01-4d67-b8c1-eb99d36eed3e,Microsoft Stream for Office 365 E5 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,TEAMS1,57ff2da0-773e-42df-b2af-ffb7a2317929,Microsoft Teams +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MINECRAFT_EDUCATION_EDITION,4c246bbc-f513-4311-beff-eba54c353256,Minecraft Education Edition +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_O365,882e1d05-acd1-4ccb-8708-6ee03664b117,Mobile Device Management for Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Nucleus,db4d623d-b514-490b-b7ef-8885eee514de,Nucleus +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EQUIVIO_ANALYTICS,4de31727-a228-4ec3-a5bf-8e45b5ca48cc,Office 365 Advanced eDiscovery +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ADALLOM_S_O365,8c098270-9dd4-4350-9b30-ba4703f3b36b,Office 365 Cloud App Security +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PAM_ENTERPRISE,b1188c4c-1b36-4018-b48b-ee07604f6feb,Office 365 Privileged Access Management +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SAFEDOCS,bf6f5520-59e3-4f82-974b-7dbbc4fd27c7,Office 365 SafeDocs +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SHAREPOINTWAC_EDU,e03c7e47-402c-463c-ab25-949079bedb21,Office for the Web for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,POWERAPPS_O365_P3,9c0dab89-a30c-4117-86e7-97bda240acd2,Power Apps for Office 365 (Plan 3) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,BI_AZURE_P2,70d33638-9c74-4d01-bfd3-562de28bd4ba,Power BI Pro +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PREMIUM_ENCRYPTION,617b097b-4b93-4ede-83de-5f075bb5fb2f,Premium Encryption in Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PROJECT_O365_P3,b21a6b06-1988-436e-a07b-51ec6d9f52ad,Project for Office (Plan E5) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PURVIEW_DISCOVERY,c948ea65-2053-4a5a-8a62-9eaaaf11b522,Purview Discovery +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Bing_Chat_Enterprise,0d0c0d31-fae7-41f2-b909-eaf4d7f26dba,RETIRED - Commercial data protection for Microsoft Copilot +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMUNICATIONS_COMPLIANCE,41fcdd7d-4733-4863-9cf4-c65b83ce2df4,RETIRED - Microsoft Communications Compliance +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,DATA_INVESTIGATIONS,46129a58-a698-46f0-aa5b-17f6586297d9,Retired - Microsoft Data Investigations +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SCHOOL_DATA_SYNC_P2,500b6a2a-7a50-4f40-b5f9-160e5b8c2f48,School Data Sync (Plan 2) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SHAREPOINTENTERPRISE_EDU,63038b2c-28d0-45f6-bc36-33062963b498,SharePoint (Plan 2) for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SWAY,a23b959c-7ce8-4e57-9140-b90eb88a9e97,Sway +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,BPOS_S_TODO_3,3fb82609-8c27-4f7b-bd51-30634711ee67,To-Do (Plan 3) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,VIVA_LEARNING_SEEDED,b76fb638-6ba6-402a-b9f9-83d28acb3d86,Viva Learning Seeded +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WHITEBOARD_PLAN3,4a51bca5-1eff-43f5-878c-177680f191af,Whiteboard (Plan 3) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WINDEFATP,871d91ec-ec1a-452b-a83f-bd76c7d770ef,Microsoft Defender for Endpoint +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFTENDPOINTDLP,64bfac92-2b17-4482-b5e5-a0304429de3e,Microsoft Endpoint DLP +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,UNIVERSAL_PRINT_01,795f6fe0-cc4d-4773-b050-5dde4dc704c9,Universal Print +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Virtualization Rights for Windows 10 (E3/E5+VDA),e7c91390-7625-45be-94e0-e16907e03118,Windows 10/11 Enterprise +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WINDOWSUPDATEFORBUSINESS_DEPLOYMENTSERVICE,7bf960f6-2cd9-443a-8046-5dbff9558365,Windows Update for Business Deployment Service +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_PREMIUM,6c57d4b6-3b23-47a5-9bc9-69f17b4947b3,Azure Information Protection Premium P1 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_PREMIUM2,5689bec4-755d-4753-8b61-40975025187c,Azure Information Protection Premium P2 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,DYN365_CDS_O365_P3,28b0fa46-c39a-4188-89e2-58e979a6b014,Common Data Service +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Intune_ServiceNow,3eeb8536-fecf-41bf-a3f8-d6f17a9f3efc,Intune ServiceNow Integration +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MFA_PREMIUM,8a256a2b-b617-496d-b51b-e76466e88db0,Microsoft Azure Multi-Factor Authentication +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ADALLOM_S_STANDALONE,2e2ddb96-6af9-4b1d-a3f0-d6ecfd22edb2,Microsoft Defender for Cloud Apps +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ATA,14ab5db5-e6c4-4b20-b4bc-13e36fd2227f,Microsoft Defender for Identity +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_PREMIUM_P2,eec0eb4f-6444-4f95-aba0-50c24d67f998,Microsoft Entra ID P2 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune Plan 1 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune Plan 1 for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,FLOW_O365_P3,07699545-9485-468e-95b6-2fca3738be01,Power Automate for Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,POWER_VIRTUAL_AGENTS_O365_P3,ded3d325-1bdc-453e-8432-5bac26d7a014,Power Virtual Agents for Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,REMOTE_HELP,a4c6cf29-1168-4076-ba5c-e8fe0e62b17e,Remote help +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,CDS_O365_P3,afa73018-811e-46e9-988f-f75d2b1b8430,Common Data Service for Teams Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,LOCKBOX_ENTERPRISE,9f431833-0334-42de-a7dc-70aa40db46db,Customer Lockbox +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,CustomerLockboxA_Enterprise,3ec18638-bd4c-4d3b-8905-479ed636b83e,Customer Lockbox (A) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MIP_S_Exchange,cd31b152-6326-4d1b-ae1b-997b625182e6,Data Classification in Microsoft 365 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,COMMON_DEFENDER_PLATFORM_FOR_OFFICE,a312bdeb-1e21-40d0-84b1-0e73f128144f,Defender Platform for Office 365 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,EXCHANGE_S_ENTERPRISE,efb87545-963c-4e0d-99df-69c6916d9eb0,Exchange Online (Plan 2) +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,GRAPH_CONNECTORS_SEARCH_INDEX,a6520331-d7d4-4276-95f5-15c0933bc757,Graph Connectors Search with Index Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,Content_Explorer,d9fa6af4-e046-4c89-9226-729a0786685d,Information Protection and Governance Analytics - Premium Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ContentExplorer_Standard,2b815d45-56e4-4e3a-b65c-66cb9175b560,Information Protection and Governance Analytics – Standard Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MIP_S_CLP2,efb0351d-3b08-4503-993d-383af8de41e3,Information Protection for Office 365 - Premium Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MIP_S_CLP1,5136a095-5cf0-4aff-bec3-e84448b38ea5,Information Protection for Office 365 - Standard Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,M365_ADVANCED_AUDITING,2f442157-a11c-46b9-ae5b-6e39ff4e5849,Microsoft 365 Advanced Auditing -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,OFFICESUBSCRIPTION,43de0ff5-c92c-492b-9116-175376d08c38,Microsoft 365 Apps for Enterprise +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,OFFICESUBSCRIPTION,43de0ff5-c92c-492b-9116-175376d08c38,Microsoft 365 Apps for enterprise Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,M365_AUDIT_PLATFORM,f6de4823-28fa-440b-b886-4783fa86ddba,Microsoft 365 Audit Platform Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MICROSOFT_COMMUNICATION_COMPLIANCE,a413a9ff-720c-4822-98ef-2f37c2a21f4c,Microsoft 365 Communication Compliance Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MTP,bf28f719-7844-4079-9c78-c1307898e192,Microsoft 365 Defender +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MICROSOFTBOOKINGS,199a5c09-e0ca-4e37-8f7c-b05d533e1ea2,Microsoft Bookings +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,CLIPCHAMP,a1ace008-72f3-4ea0-8dac-33b3a23a2472,Microsoft Clipchamp Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,COMMUNICATIONS_DLP,6dc145d6-95dd-4191-b9c3-185575ee6f6b,Microsoft Communications DLP Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,CUSTOMER_KEY,6db1f1db-2b46-403f-be40-e39395f08dbb,Microsoft Customer Key -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,DATA_INVESTIGATIONS,46129a58-a698-46f0-aa5b-17f6586297d9,Microsoft Data Investigations Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ATP_ENTERPRISE,f20fedf3-f3c3-43c3-8267-2bfdd51c0939,Microsoft Defender for Office 365 (Plan 1) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,THREAT_INTELLIGENCE,8e0c0a52-6a6c-4d40-8370-dd62790dcd70,Microsoft Defender for Office 365 (Plan 2) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,EXCEL_PREMIUM,531ee2f8-b1cb-453b-9c21-d2180d014ca5,Microsoft Excel Advanced Analytics Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,OFFICE_FORMS_PLAN_3,96c1e14a-ef43-418d-b115-9636cdaa8eed,Microsoft Forms (Plan 3) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INFO_GOVERNANCE,e26c2fcc-ab91-4a61-b35c-03cdc8dddf66,Microsoft Information Governance Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INSIDER_RISK,d587c7a3-bda9-4f99-8776-9bcf59c84f75,Microsoft Insider Risk Management +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INSIDER_RISK_MANAGEMENT,9d0c4ee5-e4a1-4625-ab39-d82b619b1a34,Microsoft Insider Risk Management - Exchange Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,KAIZALA_STANDALONE,0898bdbb-73b0-471a-81e5-20f1fe4dd66e,Microsoft Kaizala Pro +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MICROSOFT_LOOP,c4b8c31a-fb44-4c65-9837-a21f55fcabda,Microsoft Loop Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ML_CLASSIFICATION,d2d51368-76c9-4317-ada2-a12c004c432f,Microsoft ML-Based Classification Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,EXCHANGE_ANALYTICS,34c0d7a0-a70f-4668-9238-47f9fc208882,Microsoft MyAnalytics (Full) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner @@ -1091,8 +1117,10 @@ Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,BI_AZURE_P2,70d33638-9c74-4d01-bfd3-562de28bd4ba,Power BI Pro Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,PREMIUM_ENCRYPTION,617b097b-4b93-4ede-83de-5f075bb5fb2f,Premium Encryption in Office 365 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,PROJECT_O365_P3,b21a6b06-1988-436e-a07b-51ec6d9f52ad,Project for Office (Plan E5) +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,PURVIEW_DISCOVERY,c948ea65-2053-4a5a-8a62-9eaaaf11b522,Purview Discovery +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,Bing_Chat_Enterprise,0d0c0d31-fae7-41f2-b909-eaf4d7f26dba,RETIRED - Commercial data protection for Microsoft Copilot Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,COMMUNICATIONS_COMPLIANCE,41fcdd7d-4733-4863-9cf4-c65b83ce2df4,RETIRED - Microsoft Communications Compliance -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INSIDER_RISK_MANAGEMENT,9d0c4ee5-e4a1-4625-ab39-d82b619b1a34,RETIRED - Microsoft Insider Risk Management +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,DATA_INVESTIGATIONS,46129a58-a698-46f0-aa5b-17f6586297d9,Retired - Microsoft Data Investigations Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,SCHOOL_DATA_SYNC_P2,500b6a2a-7a50-4f40-b5f9-160e5b8c2f48,School Data Sync (Plan 2) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,SHAREPOINTENTERPRISE_EDU,63038b2c-28d0-45f6-bc36-33062963b498,SharePoint (Plan 2) for Education Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) @@ -1105,18 +1133,20 @@ Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,UNIVERSAL_PRINT_01,795f6fe0-cc4d-4773-b050-5dde4dc704c9,Universal Print Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,Virtualization Rights for Windows 10 (E3/E5+VDA),e7c91390-7625-45be-94e0-e16907e03118,Windows 10/11 Enterprise Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,WINDOWSUPDATEFORBUSINESS_DEPLOYMENTSERVICE,7bf960f6-2cd9-443a-8046-5dbff9558365,Windows Update for Business Deployment Service -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_PREMIUM_P2,eec0eb4f-6444-4f95-aba0-50c24d67f998,Microsoft Entra ID P2 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,RMS_S_PREMIUM,6c57d4b6-3b23-47a5-9bc9-69f17b4947b3,Azure Information Protection Premium P1 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,RMS_S_PREMIUM2,5689bec4-755d-4753-8b61-40975025187c,Azure Information Protection Premium P2 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,DYN365_CDS_O365_P3,28b0fa46-c39a-4188-89e2-58e979a6b014,Common Data Service +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,Intune_ServiceNow,3eeb8536-fecf-41bf-a3f8-d6f17a9f3efc,Intune ServiceNow Integration Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MFA_PREMIUM,8a256a2b-b617-496d-b51b-e76466e88db0,Microsoft Azure Multi-Factor Authentication Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ADALLOM_S_STANDALONE,2e2ddb96-6af9-4b1d-a3f0-d6ecfd22edb2,Microsoft Defender for Cloud Apps Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ATA,14ab5db5-e6c4-4b20-b4bc-13e36fd2227f,Microsoft Defender for Identity -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune for Education +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_PREMIUM_P2,eec0eb4f-6444-4f95-aba0-50c24d67f998,Microsoft Entra ID P2 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune Plan 1 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune Plan 1 for Education Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,FLOW_O365_P3,07699545-9485-468e-95b6-2fca3738be01,Power Automate for Office 365 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,POWER_VIRTUAL_AGENTS_O365_P3,ded3d325-1bdc-453e-8432-5bac26d7a014,Power Virtual Agents for Office 365 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,REMOTE_HELP,a4c6cf29-1168-4076-ba5c-e8fe0e62b17e,Remote help Microsoft 365 A5 for students use benefit,M365EDU_A5_STUUSEBNFT,31d57bc7-3a05-4867-ab53-97a17835a411,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education Microsoft 365 A5 for students use benefit,M365EDU_A5_STUUSEBNFT,31d57bc7-3a05-4867-ab53-97a17835a411,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management Microsoft 365 A5 for students use benefit,M365EDU_A5_STUUSEBNFT,31d57bc7-3a05-4867-ab53-97a17835a411,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics @@ -3633,13 +3663,19 @@ Microsoft Dynamics CRM Online,CRMSTANDARD,d17b27af-3f49-4822-99f9-56a661538792,M Microsoft Dynamics CRM Online,CRMSTANDARD,d17b27af-3f49-4822-99f9-56a661538792,NBPROFESSIONALFORCRM,3e58e97c-9abe-ebab-cd5f-d543d1529634,MICROSOFT SOCIAL ENGAGEMENT PROFESSIONAL - ELIGIBILITY CRITERIA APPLY Microsoft Dynamics CRM Online,CRMSTANDARD,d17b27af-3f49-4822-99f9-56a661538792,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,POWERAPPS FOR DYNAMICS 365 Microsoft Entra ID Governance,Microsoft_Entra_ID_Governance,cf6b0d46-4093-4546-a0ab-0b1546dcc10e,Entra_Identity_Governance,e866a266-3cff-43a3-acca-0c90a7e00c8b,Entra Identity Governance +Microsoft Entra Suite Add-on for Microsoft Entra ID P2,Microsoft_Entra_Suite_Step_Up_for_Microsoft_Entra_ID_P2,2ef3064c-c95c-426c-96dd-9ffeaa2f2c37,Entra_Premium_Internet_Access,8d23cb83-ab07-418f-8517-d7aca77307dc,Microsoft Entra Internet Access +Microsoft Entra Suite Add-on for Microsoft Entra ID P2,Microsoft_Entra_Suite_Step_Up_for_Microsoft_Entra_ID_P2,2ef3064c-c95c-426c-96dd-9ffeaa2f2c37,Entra_Premium_Private_Access,f057aab1-b184-49b2-85c0-881b02a405c5,Microsoft Entra Private Access +Microsoft Entra Suite Add-on for Microsoft Entra ID P2,Microsoft_Entra_Suite_Step_Up_for_Microsoft_Entra_ID_P2,2ef3064c-c95c-426c-96dd-9ffeaa2f2c37,Verifiable_Credentials_Service_Request,aae826b7-14cd-4691-8178-2b312f7072ea,Verifiable Credentials Service Request +Microsoft Entra Suite Add-on for Microsoft Entra ID P2,Microsoft_Entra_Suite_Step_Up_for_Microsoft_Entra_ID_P2,2ef3064c-c95c-426c-96dd-9ffeaa2f2c37,Entra_Identity_Governance,e866a266-3cff-43a3-acca-0c90a7e00c8b,Entra Identity Governance Microsoft Fabric (Free),POWER_BI_STANDARD,a403ebcc-fae0-4ca2-8c8c-7a907fd6c235,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Microsoft Fabric (Free),POWER_BI_STANDARD,a403ebcc-fae0-4ca2-8c8c-7a907fd6c235,BI_AZURE_P0,2049e525-b859-401b-b2a0-e0a31c4b1fe4,Power BI (free) +Microsoft Fabric (Free),POWER_BI_STANDARD,a403ebcc-fae0-4ca2-8c8c-7a907fd6c235,PURVIEW_DISCOVERY,c948ea65-2053-4a5a-8a62-9eaaaf11b522,Purview Discovery Microsoft Fabric (Free) for faculty,POWER_BI_STANDARD_FACULTY,ade29b5f-397e-4eb9-a287-0344bd46c68d,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,EXCHANGE_S_FOUNDATION Microsoft Fabric (Free) for faculty,POWER_BI_STANDARD_FACULTY,ade29b5f-397e-4eb9-a287-0344bd46c68d,BI_AZURE_P0,2049e525-b859-401b-b2a0-e0a31c4b1fe4,BI_AZURE_P0 Microsoft Fabric (Free) for student,POWER_BI_STANDARD_STUDENT,bdcaf6aa-04c1-4b8f-b64e-6e3bd505ac64,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,EXCHANGE_S_FOUNDATION Microsoft Fabric (Free) for student,POWER_BI_STANDARD_STUDENT,bdcaf6aa-04c1-4b8f-b64e-6e3bd505ac64,BI_AZURE_P0,2049e525-b859-401b-b2a0-e0a31c4b1fe4,BI_AZURE_P0 Microsoft Imagine Academy,IT_ACADEMY_AD,ba9a34de-4489-469d-879c-0f0f145321cd,IT_ACADEMY_AD,d736def0-1fde-43f0-a5be-e3f8b2de6e41,MS IMAGINE ACADEMY +Microsoft Intune Advanced Analytics,Microsoft_Intune_Advanced_Analytics,5e36d0d4-e9e5-4052-aba0-0257465c9b86,Intune_AdvancedEA,2a4baa0e-5e99-4c38-b1f2-6864960f1bd1,Microsoft Intune Advanced Analytics Microsoft Intune Device,INTUNE_A_D,2b317a4a-77a6-4188-9437-b68a77b4e2c6,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Microsoft Intune Device,INTUNE_A_D,2b317a4a-77a6-4188-9437-b68a77b4e2c6,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune Microsoft Intune Device for Government,INTUNE_A_D_GOV,2c21e77a-e0d6-4570-b38a-7ff2dc17d2ca,EXCHANGE_S_FOUNDATION_GOV,922ba911-5694-4e99-a794-73aed9bfeec8,Exchange Foundation for Government @@ -3696,6 +3732,10 @@ Microsoft Stream Storage Add-On (500 GB),STREAM_STORAGE,9bd7c846-9556-4453-a542- Microsoft Sustainability Manager Premium,Microsoft_Sustainability_Manager_Premium,aecb477b-2f56-4e38-b711-b752c24fc19b,CDS_CLOUD_FOR_SUSTAINABILITY_PLUS,ba80223c-e515-4642-a838-3e7d66f70cb6,Common Data Services for Cloud for Sustainability Plus Microsoft Sustainability Manager Premium,Microsoft_Sustainability_Manager_Premium,aecb477b-2f56-4e38-b711-b752c24fc19b,MCS_BIZAPPS_CLOUD_FOR_SUSTAINABILITY_PLUS,ed29ae92-ff5f-4446-8460-83c54d0e7088,MCS - BizApps Cloud for Sustainability Plus Microsoft Sustainability Manager Premium,Microsoft_Sustainability_Manager_Premium,aecb477b-2f56-4e38-b711-b752c24fc19b,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +Microsoft Sustainability Manager Premium USL Plus,MICROSOFT_SUSTAINABILITY_MANAGER_PREMIUM_USL_ADDON,9d576ffb-dd32-4c33-91ee-91625b61424a,MCS_BIZAPPS_CLOUD_FOR_SUSTAINABILITY_USL_PLUS,beaf5b5c-d11c-4417-b5cb-cd9f9e6719b0,MCS - BizApps Cloud for Sustainability USL Plus +Microsoft Sustainability Manager Premium USL Plus,MICROSOFT_SUSTAINABILITY_MANAGER_PREMIUM_USL_ADDON,9d576ffb-dd32-4c33-91ee-91625b61424a,POWER_APPS_FOR_MCS_USL_PLUS,c5502fe7-406d-442a-827f-4948b821ba08,Power Apps for Cloud for Sustainability USL Plus +Microsoft Sustainability Manager Premium USL Plus,MICROSOFT_SUSTAINABILITY_MANAGER_PREMIUM_USL_ADDON,9d576ffb-dd32-4c33-91ee-91625b61424a,POWER_AUTOMATE_FOR_MCS_USL_PLUS,1c22bb50-96fb-49e5-baa6-195cab19eee2,Power Automate for Cloud for Sustainability USL Plus +Microsoft Sustainability Manager Premium USL Plus,MICROSOFT_SUSTAINABILITY_MANAGER_PREMIUM_USL_ADDON,9d576ffb-dd32-4c33-91ee-91625b61424a,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Microsoft Sustainability Manager USL Essentials,Microsoft_Cloud_for_Sustainability_USL,ece037b4-a52b-4cf8-93ea-649e5d83767a,MCS_BizApps_Cloud_for_Sustainability_USL,c46c42af-d654-4385-8c85-29a84f3dfb22,MCS - BizApps - Cloud for Sustainability USL Microsoft Sustainability Manager USL Essentials,Microsoft_Cloud_for_Sustainability_USL,ece037b4-a52b-4cf8-93ea-649e5d83767a,POWER_APPS_FOR_MCS_USL,5ffd371c-037a-41a2-98a3-6452f8c5de17,Power Apps for Cloud for Sustainability USL Microsoft Sustainability Manager USL Essentials,Microsoft_Cloud_for_Sustainability_USL,ece037b4-a52b-4cf8-93ea-649e5d83767a,POWER_AUTOMATE_FOR_MCS_USL,ccbe468e-7973-442c-8ec4-5fbe16438711,Power Automate for Cloud for Sustainability USL @@ -3808,18 +3848,20 @@ Microsoft Teams Rooms Pro,Microsoft_Teams_Rooms_Pro,4cde982a-ede4-4409-9ae6-b003 Microsoft Teams Rooms Pro,Microsoft_Teams_Rooms_Pro,4cde982a-ede4-4409-9ae6-b003453c8ea6,TEAMS1,57ff2da0-773e-42df-b2af-ffb7a2317929,Microsoft Teams Microsoft Teams Rooms Pro,Microsoft_Teams_Rooms_Pro,4cde982a-ede4-4409-9ae6-b003453c8ea6,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) Microsoft Teams Rooms Pro,Microsoft_Teams_Rooms_Pro,4cde982a-ede4-4409-9ae6-b003453c8ea6,WHITEBOARD_PLAN3,4a51bca5-1eff-43f5-878c-177680f191af,Whiteboard (Plan 3) -Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education +Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,TEAMS1,57ff2da0-773e-42df-b2af-ffb7a2317929,Microsoft Teams Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,MTRProManagement,ecc74eae-eeb7-4ad5-9c88-e8b2bfca75b8,Microsoft Teams Rooms Pro Management Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) +Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,Teams_Rooms_Pro,0374d34c-6be4-4dbb-b3f0-26105db0b28a,Teams Rooms Pro Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,Teams_Room_Basic,8081ca9c-188c-4b49-a8e5-c23b5e9463a8,Teams Rooms Test 1 Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,Teams_Room_Pro,ec17f317-f4bc-451e-b2da-0167e5c260f9,Teams Rooms Test 2 Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,WHITEBOARD_PLAN3,4a51bca5-1eff-43f5-878c-177680f191af,Whiteboard (Plan 3) Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,WINDEFATP,871d91ec-ec1a-452b-a83f-bd76c7d770ef,Microsoft Defender for Endpoint Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune Plan 1 +Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,SPECIALTY_DEVICES,cfce7ae3-4b41-4438-999c-c0e91f3b7fb9,Specialty devices Microsoft Teams Rooms Pro for GCC,Microsoft_Teams_Rooms_Pro_GCC,31ecb341-2a17-483e-9140-c473006d1e1a,MCOMEETADV_GOV,f544b08d-1645-4287-82de-8d91f37c02a1,Microsoft 365 Audio Conferencing for Government Microsoft Teams Rooms Pro for GCC,Microsoft_Teams_Rooms_Pro_GCC,31ecb341-2a17-483e-9140-c473006d1e1a,MCOEV_GOV,db23fce2-a974-42ef-9002-d78dd42a0f22,Microsoft 365 Phone System for Government Microsoft Teams Rooms Pro for GCC,Microsoft_Teams_Rooms_Pro_GCC,31ecb341-2a17-483e-9140-c473006d1e1a,TEAMS_GOV,304767db-7d23-49e8-a945-4a7eb65f9f28,Microsoft Teams for Government @@ -3914,14 +3956,14 @@ Office 365 Multi-Geo Capabilities,OFFICE365_MULTIGEO,84951599-62b7-46f3-9c9d-305 Office 365 Multi-Geo Capabilities,OFFICE365_MULTIGEO,84951599-62b7-46f3-9c9d-30551b2ad607,TEAMSMULTIGEO,41eda15d-6b52-453b-906f-bc4a5b25a26b,Teams Multi-Geo Nonprofit Portal,NONPROFIT_PORTAL,aa2695c9-8d59-4800-9dc8-12e01f1735af,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Nonprofit Portal,NONPROFIT_PORTAL,aa2695c9-8d59-4800-9dc8-12e01f1735af,NONPROFIT_PORTAL,7dbc2d88-20e2-4eb6-b065-4510b38d6eb2,Nonprofit Portal -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service - O365 P1 +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,EXCHANGE_S_STANDARD,9aaf7827-d63c-4b61-89c3-182f06f82e5c,Exchange Online (Plan 1) Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Microsoft Microsoft Entra Rights +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,OFFICE_FORMS_PLAN_2,9b5de886-f035-4ff2-b3d8-c9127bea3620,Microsoft Forms (Plan 2) -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,KAIZALA_O365_P2,54fc630f-5a40-48ee-8965-af0503c1386e,Microsoft Kaizala Pro Plan 2 +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,KAIZALA_O365_P2,54fc630f-5a40-48ee-8965-af0503c1386e,Microsoft Kaizala Pro Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,MICROSOFT_SEARCH,94065c59-bc8e-4e8b-89e5-5138d471eaff,Microsoft Search Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,Deskless,8c7d2df8-86f0-4902-b2ed-a0458298f3b3,Microsoft StaffHub @@ -3931,9 +3973,8 @@ Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c897 Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,Nucleus,db4d623d-b514-490b-b7ef-8885eee514de,Nucleus Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,SHAREPOINTWAC_EDU,e03c7e47-402c-463c-ab25-949079bedb21,Office for the Web for Education Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,OFFICEMOBILE_SUBSCRIPTION,c63d4d19-e8cb-460e-b37c-4d6c34603745,Office Mobile Apps for Office 365 -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,PROJECT_O365_P1,a55dfd10-0864-46d9-a3cd-da5991a3e0e2,Project for Office (Plan E1) +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,Bing_Chat_Enterprise,0d0c0d31-fae7-41f2-b909-eaf4d7f26dba,RETIRED - Commercial data protection for Microsoft Copilot Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,SCHOOL_DATA_SYNC_P1,c33802dd-1b50-4b9a-8bb9-f13d2cdeadac,School Data Sync (Plan 1) Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,SHAREPOINTSTANDARD_EDU,0a4983bb-d3e5-4a09-95d8-b2d0127b3df5,SharePoint (Plan 1) for Education Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) @@ -3942,6 +3983,9 @@ Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c897 Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,VIVA_LEARNING_SEEDED,b76fb638-6ba6-402a-b9f9-83d28acb3d86,Viva Learning Seeded Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,WHITEBOARD_PLAN1,b8afc642-032e-4de5-8c0a-507a7bba7e5d,Whiteboard (Plan 1) Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service - O365 P1 Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics @@ -3969,14 +4013,14 @@ Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-89 Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,VIVA_LEARNING_SEEDED,b76fb638-6ba6-402a-b9f9-83d28acb3d86,Viva Learning Seeded Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,WHITEBOARD_PLAN1,b8afc642-032e-4de5-8c0a-507a7bba7e5d,Whiteboard (Plan 1) Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service - O365 P1 +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,EXCHANGE_S_STANDARD,9aaf7827-d63c-4b61-89c3-182f06f82e5c,Exchange Online (Plan 1) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Microsoft Microsoft Entra Rights +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,OFFICE_FORMS_PLAN_2,9b5de886-f035-4ff2-b3d8-c9127bea3620,Microsoft Forms (Plan 2) -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,KAIZALA_O365_P2,54fc630f-5a40-48ee-8965-af0503c1386e,Microsoft Kaizala Pro Plan 2 +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,KAIZALA_O365_P2,54fc630f-5a40-48ee-8965-af0503c1386e,Microsoft Kaizala Pro Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,MICROSOFT_SEARCH,94065c59-bc8e-4e8b-89e5-5138d471eaff,Microsoft Search Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,Deskless,8c7d2df8-86f0-4902-b2ed-a0458298f3b3,Microsoft StaffHub @@ -3985,9 +4029,8 @@ Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4 Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,INTUNE_O365,882e1d05-acd1-4ccb-8708-6ee03664b117,Mobile Device Management for Office 365 Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,SHAREPOINTWAC_EDU,e03c7e47-402c-463c-ab25-949079bedb21,Office for the Web for Education Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,OFFICEMOBILE_SUBSCRIPTION,c63d4d19-e8cb-460e-b37c-4d6c34603745,Office Mobile Apps for Office 365 -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,PROJECT_O365_P1,a55dfd10-0864-46d9-a3cd-da5991a3e0e2,Project for Office (Plan E1) +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,Bing_Chat_Enterprise,0d0c0d31-fae7-41f2-b909-eaf4d7f26dba,RETIRED - Commercial data protection for Microsoft Copilot Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,SCHOOL_DATA_SYNC_P1,c33802dd-1b50-4b9a-8bb9-f13d2cdeadac,School Data Sync (Plan 1) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,SHAREPOINTSTANDARD_EDU,0a4983bb-d3e5-4a09-95d8-b2d0127b3df5,SharePoint (Plan 1) for Education Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) @@ -3995,6 +4038,9 @@ Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4 Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,BPOS_S_TODO_2,c87f142c-d1e9-4363-8630-aaea9c4d9ae5,To-Do (Plan 2) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,WHITEBOARD_PLAN1,b8afc642-032e-4de5-8c0a-507a7bba7e5d,Whiteboard (Plan 1) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 Office 365 A1 Plus for students,STANDARDWOFFPACK_IW_STUDENT,e82ae690-a2d5-4d76-8d30-7c6e01e6022e,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education Office 365 A1 Plus for students,STANDARDWOFFPACK_IW_STUDENT,e82ae690-a2d5-4d76-8d30-7c6e01e6022e,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service - O365 P1 Office 365 A1 Plus for students,STANDARDWOFFPACK_IW_STUDENT,e82ae690-a2d5-4d76-8d30-7c6e01e6022e,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics @@ -5059,8 +5105,11 @@ Power Apps Per User BD Only,POWERAPPS_PER_USER_BD_ONLY,2ced8a00-3ed1-4295-ab7c-5 Power Apps Per User BD Only,POWERAPPS_PER_USER_BD_ONLY,2ced8a00-3ed1-4295-ab7c-57170ff28e58,CDS_ POWERAPPS_PER_USER_CUSTOM,2e8dde43-6986-479d-b179-7dbe31c31f60,CDS Power Apps Per User Custom Power Apps Per User BD Only,POWERAPPS_PER_USER_BD_ONLY,2ced8a00-3ed1-4295-ab7c-57170ff28e58,POWERAPPS_PER_USER,ea2cf03b-ac60-46ae-9c1d-eeaeb63cec86,Power Apps per User Plan Power Apps Per User BD Only,POWERAPPS_PER_USER_BD_ONLY,2ced8a00-3ed1-4295-ab7c-57170ff28e58,Flow_PowerApps_PerUser,dc789ed8-0170-4b65-a415-eb77d5bb350a,Power Automate for Power Apps per User Plan -Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,DYN365_CDS_P2,6ea4c1ef-c259-46df-bce2-943342cd3cb2,Common Data Service - P2 +Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,CDSAICAPACITY_PERUSER_NEW,74d93933-6f22-436e-9441-66d205435abb,AI Builder capacity Per User add-on +Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,DYN365_CDS_P2,6ea4c1ef-c259-46df-bce2-943342cd3cb2,Common Data Service +Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,CDSAICAPACITY_PERUSER,91f50f7b-2204-4803-acac-5cf5668b8b39,DO NOT USE - AI Builder capacity Per User add-on Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,POWERAPPS_PER_USER,ea2cf03b-ac60-46ae-9c1d-eeaeb63cec86,Power Apps per User Plan Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,Flow_PowerApps_PerUser,dc789ed8-0170-4b65-a415-eb77d5bb350a,Power Automate for Power Apps per User Plan Power Apps Premium for Government,POWERAPPS_PER_USER_GCC,8e4c6baa-f2ff-4884-9c38-93785d0d7ba1,CDSAICAPACITY_PERUSER,91f50f7b-2204-4803-acac-5cf5668b8b39,AI Builder capacity Per User add-on @@ -5130,6 +5179,8 @@ Power BI Premium Per User,PBI_PREMIUM_PER_USER,c1d032e0-5619-4761-9b5c-75b6831e1 Power BI Premium Per User,PBI_PREMIUM_PER_USER,c1d032e0-5619-4761-9b5c-75b6831e1711,BI_AZURE_P3,0bf3c642-7bb5-4ccc-884e-59d09df0266c,Power BI Premium Per User Power BI Premium Per User,PBI_PREMIUM_PER_USER,c1d032e0-5619-4761-9b5c-75b6831e1711,BI_AZURE_P2,70d33638-9c74-4d01-bfd3-562de28bd4ba,Power BI Pro Power BI Premium Per User Add-On,PBI_PREMIUM_PER_USER_ADDON,de376a03-6e5b-42ec-855f-093fb50b8ca5,BI_AZURE_P3,0bf3c642-7bb5-4ccc-884e-59d09df0266c,Power BI Premium Per User +Power BI Premium Per User Add-On for Faculty,PBI_PREMIUM_PER_USER_ADDON_FACULTY,c05b235f-be75-4029-8851-6a4170758eef,BI_AZURE_P3,0bf3c642-7bb5-4ccc-884e-59d09df0266c,Power BI Premium Per User +Power BI Premium Per User Add-On for Faculty,PBI_PREMIUM_PER_USER_ADDON_FACULTY,c05b235f-be75-4029-8851-6a4170758eef,PURVIEW_DISCOVERY,c948ea65-2053-4a5a-8a62-9eaaaf11b522,Purview Discovery Power BI Premium Per User Add-On for GCC,PBI_PREMIUM_PER_USER_ADDON_CE_GCC,66024bbf-4cd4-4329-95c8-c932e2ae01a8,BI_AZURE_P3_GOV,32d15238-9a8c-46da-af3f-21fc5351d365,Power BI Premium Per User for Government Power BI Premium Per User Add-On for GCC,PBI_PREMIUM_PER_USER_ADDON_GCC,1b572d5e-1bf8-4b19-9259-f9eda31a6972,BI_AZURE_P3_GOV,32d15238-9a8c-46da-af3f-21fc5351d365,Power BI Premium Per User for Government Power BI Premium Per User Dept,PBI_PREMIUM_PER_USER_DEPT,f168a3fb-7bcf-4a27-98c3-c235ea4b78b4,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation @@ -5426,6 +5477,14 @@ Teams Premium (for Departments),Teams_Premium_(for_Departments),52ea0e27-ae73-49 Teams Premium (for Departments),Teams_Premium_(for_Departments),52ea0e27-ae73-4983-a08f-13561ebdb823,TEAMSPRO_VIRTUALAPPT,9104f592-f2a7-4f77-904c-ca5a5715883f,Microsoft Teams Premium Virtual Appointment Teams Premium (for Departments),Teams_Premium_(for_Departments),52ea0e27-ae73-4983-a08f-13561ebdb823,MCO_VIRTUAL_APPT,711413d0-b36e-4cd4-93db-0a50a4ab7ea3,Microsoft Teams Premium Virtual Appointments Teams Premium (for Departments),Teams_Premium_(for_Departments),52ea0e27-ae73-4983-a08f-13561ebdb823,TEAMSPRO_WEBINAR,78b58230-ec7e-4309-913c-93a45cc4735b,Microsoft Teams Premium Webinar +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,MICROSOFT_ECDN,85704d55-2e73-47ee-93b4-4b8ea14db92b,Microsoft eCDN +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_MGMT,0504111f-feb8-4a3c-992a-70280f9a2869,Microsoft Teams Premium Intelligent +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_CUST,cc8c0802-a325-43df-8cba-995d0c6cb373,Microsoft Teams Premium Personalized +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_PROTECTION,f8b44f54-18bb-46a3-9658-44ab58712968,Microsoft Teams Premium Secure +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_VIRTUALAPPT,9104f592-f2a7-4f77-904c-ca5a5715883f,Microsoft Teams Premium Virtual Appointment +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,MCO_VIRTUAL_APPT,711413d0-b36e-4cd4-93db-0a50a4ab7ea3,Microsoft Teams Premium Virtual Appointments +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_WEBINAR,78b58230-ec7e-4309-913c-93a45cc4735b,Microsoft Teams Premium Webinar +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,QUEUES_APP,ab2d4fb5-f80a-4bf1-a11d-7f1da254041b,Queues app for Microsoft Teams Teams Rooms Premium,MTR_PREM,4fb214cb-a430-4a91-9c91-4976763aa78f,MMR_P1,bdaa59a3-74fd-4137-981a-31d4f84eb8a0,Meeting Room Managed Services Teams Rooms Premium,MTR_PREM,4fb214cb-a430-4a91-9c91-4976763aa78f,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing Teams Rooms Premium,MTR_PREM,4fb214cb-a430-4a91-9c91-4976763aa78f,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System diff --git a/Modules/CippExtensions/Public/ConversionTable.csv b/Modules/CippExtensions/Public/ConversionTable.csv index 704f7c507d5f..5b7cea1f09ea 100644 --- a/Modules/CippExtensions/Public/ConversionTable.csv +++ b/Modules/CippExtensions/Public/ConversionTable.csv @@ -20,6 +20,7 @@ Clipchamp Premium,Clipchamp_Premium,0fe440c5-f2bf-442b-a4f4-9a7af77a200b,ONEDRIV Clipchamp Standard,Clipchamp_Standard,481f3bc2-5756-4b28-9375-5c8c86b99e6b,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Clipchamp Standard,Clipchamp_Standard,481f3bc2-5756-4b28-9375-5c8c86b99e6b,CLIPCHAMP,a1ace008-72f3-4ea0-8dac-33b3a23a2472,Microsoft Clipchamp Clipchamp Standard,Clipchamp_Standard,481f3bc2-5756-4b28-9375-5c8c86b99e6b,ONEDRIVECLIPCHAMP,f7e5b77d-f293-410a-bae8-f941f19fe680,OneDrive for Business (Clipchamp) +Clipchamp Premium Add-on,Clipchamp_Premium_Add_on,4b2c20e4-939d-4bf4-9dd8-6870240cfe19,CLIPCHAMP_PREMIUM,430b908f-78e1-4812-b045-cf83320e7d5d,Microsoft Clipchamp Premium Microsoft 365 Audio Conferencing,MCOMEETADV,0c266dff-15dd-4b49-8397-2bb16070ed52,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing Microsoft Entra ID Basic,AAD_BASIC,2b9c8e7c-319c-43a2-a2a0-48c5c6161de7,AAD_BASIC,c4da7f8a-5ee2-4c99-a7e1-87d2df57f6fe,Microsoft Entra BASIC Microsoft Entra ID P1,AAD_PREMIUM,078d2b04-f1bd-4111-bbd4-b4b1b354cef4,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 @@ -418,6 +419,13 @@ Dynamics 365 Guides vTrial,Dynamics_365_Guides_vTrial,99cb3f83-fbec-4aa1-8262-96 Dynamics 365 Guides vTrial,Dynamics_365_Guides_vTrial,99cb3f83-fbec-4aa1-8262-9679e6df7c53,DYN365_CDS_VIRAL,17ab22cd-a0b3-4536-910a-cb6eb12696c0,Common Data Service Dynamics 365 Guides vTrial,Dynamics_365_Guides_vTrial,99cb3f83-fbec-4aa1-8262-9679e6df7c53,POWER_APPS_DYN365_VIRAL_TRIAL_MIXED_REALITY,066e2fd1-ba15-40e7-aa96-d6636b1cdf71,Power Apps for Dynamics 365 Mixed Reality Dynamics 365 Guides vTrial,Dynamics_365_Guides_vTrial,99cb3f83-fbec-4aa1-8262-9679e6df7c53,POWER_AUTOMATE_DYN365_VIRAL_TRIAL_MIXED_REALITY,26fa8a18-2812-4b3d-96b4-864818ce26be,Power Automate for Dynamics 365 Mixed Reality +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,Forms_Pro_Talent,1c4ae475-5608-43fa-b3f7-d20e07cf24b4,Microsoft Dynamics 365 Customer Voice for Talent +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,D365_HR_SELF_SERVICE_OPS,835b837b-63c1-410e-bf6b-bdef201ad129,Dynamics 365 Human Resource Self Service +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,D365_HR_OPS,8b21a5dc-5485-49ed-a2d4-0e772c830f6d,Dynamics 365 Human Resources +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,D365_HR_Attach,3219525a-4064-45ec-9c35-a33ea6b39a49,Dynamics 365 Human Resources Attach +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,D365_HR_ATTACH_OPS,90d8cb62-e98a-4639-8342-8c7d2c8215ba,Dynamics 365 Human Resources Attach License +Dynamics 365 Human Resources Attach to Qualifying Dynamics 365 Base Offer,DYN365_HUMAN_RESOURCES_ATTACH,83c489a4-94b6-4dcc-9fdc-ff9b107a4621,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 Hybrid Connector,CRM_HYBRIDCONNECTOR,de176c31-616d-4eae-829a-718918d7ec23,CRM_HYBRIDCONNECTOR,0210d5c8-49d2-4dd1-a01b-a91c7c14e0bf,CRM Hybrid Connector Dynamics 365 Hybrid Connector,CRM_HYBRIDCONNECTOR,de176c31-616d-4eae-829a-718918d7ec23,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Dynamics 365 for Marketing Additional Application,DYN365_MARKETING_APPLICATION_ADDON,99c5688b-6c75-4496-876f-07f0fbd69add,DYN365_MARKETING_APPLICATION_ADDON,51cf0638-4861-40c0-8b20-1161ab2f80be,Dynamics 365 for Marketing Additional Application @@ -967,111 +975,129 @@ Microsoft 365 A3 - Unattended License for students use benefit,M365EDU_A3_STUUSE Microsoft 365 A3 - Unattended License for students use benefit,M365EDU_A3_STUUSEBNFT_RPA1,1aa94593-ca12-4254-a738-81a5972958e8,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune for Education Microsoft 365 A3 - Unattended License for students use benefit,M365EDU_A3_STUUSEBNFT_RPA1,1aa94593-ca12-4254-a738-81a5972958e8,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 Microsoft 365 A3 - Unattended License for students use benefit,M365EDU_A3_STUUSEBNFT_RPA1,1aa94593-ca12-4254-a738-81a5972958e8,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CDS_O365_P3,afa73018-811e-46e9-988f-f75d2b1b8430,Common Data Service for Teams -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,LOCKBOX_ENTERPRISE,9f431833-0334-42de-a7dc-70aa40db46db,Customer Lockbox -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_Exchange,cd31b152-6326-4d1b-ae1b-997b625182e6,Data Classification in Microsoft 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCHANGE_S_ENTERPRISE,efb87545-963c-4e0d-99df-69c6916d9eb0,Exchange Online (Plan 2) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Content_Explorer,d9fa6af4-e046-4c89-9226-729a0786685d,Information Protection and Governance Analytics - Premium -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ContentExplorer_Standard,2b815d45-56e4-4e3a-b65c-66cb9175b560,Information Protection and Governance Analytics – Standard -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_CLP2,efb0351d-3b08-4503-993d-383af8de41e3,Information Protection for Office 365 - Premium -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_CLP1,5136a095-5cf0-4aff-bec3-e84448b38ea5,Information Protection for Office 365 - Standard -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,M365_ADVANCED_AUDITING,2f442157-a11c-46b9-ae5b-6e39ff4e5849,Microsoft 365 Advanced Auditing -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,OFFICESUBSCRIPTION,43de0ff5-c92c-492b-9116-175376d08c38,Microsoft 365 Apps for Enterprise -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_COMMUNICATION_COMPLIANCE,a413a9ff-720c-4822-98ef-2f37c2a21f4c,Microsoft 365 Communication Compliance -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MTP,bf28f719-7844-4079-9c78-c1307898e192,Microsoft 365 Defender -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFTBOOKINGS,199a5c09-e0ca-4e37-8f7c-b05d533e1ea2,Microsoft Bookings -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMUNICATIONS_DLP,6dc145d6-95dd-4191-b9c3-185575ee6f6b,Microsoft Communications DLP -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CUSTOMER_KEY,6db1f1db-2b46-403f-be40-e39395f08dbb,Microsoft Customer Key -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,DATA_INVESTIGATIONS,46129a58-a698-46f0-aa5b-17f6586297d9,Microsoft Data Investigations -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ATP_ENTERPRISE,f20fedf3-f3c3-43c3-8267-2bfdd51c0939,Microsoft Defender for Office 365 (Plan 1) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,THREAT_INTELLIGENCE,8e0c0a52-6a6c-4d40-8370-dd62790dcd70,Microsoft Defender for Office 365 (Plan 2) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCEL_PREMIUM,531ee2f8-b1cb-453b-9c21-d2180d014ca5,Microsoft Excel Advanced Analytics -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,OFFICE_FORMS_PLAN_3,96c1e14a-ef43-418d-b115-9636cdaa8eed,Microsoft Forms (Plan 3) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INFO_GOVERNANCE,e26c2fcc-ab91-4a61-b35c-03cdc8dddf66,Microsoft Information Governance -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INSIDER_RISK,d587c7a3-bda9-4f99-8776-9bcf59c84f75,Microsoft Insider Risk Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,KAIZALA_STANDALONE,0898bdbb-73b0-471a-81e5-20f1fe4dd66e,Microsoft Kaizala Pro -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ML_CLASSIFICATION,d2d51368-76c9-4317-ada2-a12c004c432f,Microsoft ML-Based Classification -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCHANGE_ANALYTICS,34c0d7a0-a70f-4668-9238-47f9fc208882,Microsoft MyAnalytics (Full) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RECORDS_MANAGEMENT,65cc641f-cccd-4643-97e0-a17e3045e541,Microsoft Records Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_SEARCH,94065c59-bc8e-4e8b-89e5-5138d471eaff,Microsoft Search -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Deskless,8c7d2df8-86f0-4902-b2ed-a0458298f3b3,Microsoft StaffHub -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,STREAM_O365_E5,6c6042f5-6f01-4d67-b8c1-eb99d36eed3e,Microsoft Stream for Office 365 E5 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,TEAMS1,57ff2da0-773e-42df-b2af-ffb7a2317929,Microsoft Teams -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MINECRAFT_EDUCATION_EDITION,4c246bbc-f513-4311-beff-eba54c353256,Minecraft Education Edition -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_O365,882e1d05-acd1-4ccb-8708-6ee03664b117,Mobile Device Management for Office 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Nucleus,db4d623d-b514-490b-b7ef-8885eee514de,Nucleus -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EQUIVIO_ANALYTICS,4de31727-a228-4ec3-a5bf-8e45b5ca48cc,Office 365 Advanced eDiscovery -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ADALLOM_S_O365,8c098270-9dd4-4350-9b30-ba4703f3b36b,Office 365 Cloud App Security -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PAM_ENTERPRISE,b1188c4c-1b36-4018-b48b-ee07604f6feb,Office 365 Privileged Access Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SAFEDOCS,bf6f5520-59e3-4f82-974b-7dbbc4fd27c7,Office 365 SafeDocs -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SHAREPOINTWAC_EDU,e03c7e47-402c-463c-ab25-949079bedb21,Office for the Web for Education -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,POWERAPPS_O365_P3,9c0dab89-a30c-4117-86e7-97bda240acd2,Power Apps for Office 365 (Plan 3) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,BI_AZURE_P2,70d33638-9c74-4d01-bfd3-562de28bd4ba,Power BI Pro -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PREMIUM_ENCRYPTION,617b097b-4b93-4ede-83de-5f075bb5fb2f,Premium Encryption in Office 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PROJECT_O365_P3,b21a6b06-1988-436e-a07b-51ec6d9f52ad,Project for Office (Plan E5) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMUNICATIONS_COMPLIANCE,41fcdd7d-4733-4863-9cf4-c65b83ce2df4,Microsoft Communications Compliance -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INSIDER_RISK_MANAGEMENT,9d0c4ee5-e4a1-4625-ab39-d82b619b1a34,Microsoft Insider Risk Management -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SCHOOL_DATA_SYNC_P2,500b6a2a-7a50-4f40-b5f9-160e5b8c2f48,School Data Sync (Plan 2) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SHAREPOINTENTERPRISE_EDU,63038b2c-28d0-45f6-bc36-33062963b498,SharePoint (Plan 2) for Education -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SWAY,a23b959c-7ce8-4e57-9140-b90eb88a9e97,Sway -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,BPOS_S_TODO_3,3fb82609-8c27-4f7b-bd51-30634711ee67,To-Do (Plan 3) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,VIVA_LEARNING_SEEDED,b76fb638-6ba6-402a-b9f9-83d28acb3d86,Viva Learning Seeded -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WHITEBOARD_PLAN3,4a51bca5-1eff-43f5-878c-177680f191af,Whiteboard (Plan 3) -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WINDEFATP,871d91ec-ec1a-452b-a83f-bd76c7d770ef,Microsoft Defender for Endpoint -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFTENDPOINTDLP,64bfac92-2b17-4482-b5e5-a0304429de3e,Microsoft Endpoint DLP -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,UNIVERSAL_PRINT_01,795f6fe0-cc4d-4773-b050-5dde4dc704c9,Universal Print -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Virtualization Rights for Windows 10 (E3/E5+VDA),e7c91390-7625-45be-94e0-e16907e03118,Windows 10/11 Enterprise -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WINDOWSUPDATEFORBUSINESS_DEPLOYMENTSERVICE,7bf960f6-2cd9-443a-8046-5dbff9558365,Windows Update for Business Deployment Service -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_PREMIUM_P2,eec0eb4f-6444-4f95-aba0-50c24d67f998,Microsoft Entra ID P2 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_PREMIUM,6c57d4b6-3b23-47a5-9bc9-69f17b4947b3,Azure Information Protection Premium P1 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_PREMIUM2,5689bec4-755d-4753-8b61-40975025187c,Azure Information Protection Premium P2 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,DYN365_CDS_O365_P3,28b0fa46-c39a-4188-89e2-58e979a6b014,Common Data Service -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MFA_PREMIUM,8a256a2b-b617-496d-b51b-e76466e88db0,Microsoft Azure Multi-Factor Authentication -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ADALLOM_S_STANDALONE,2e2ddb96-6af9-4b1d-a3f0-d6ecfd22edb2,Microsoft Defender for Cloud Apps -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ATA,14ab5db5-e6c4-4b20-b4bc-13e36fd2227f,Microsoft Defender for Identity -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune for Education -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,FLOW_O365_P3,07699545-9485-468e-95b6-2fca3738be01,Power Automate for Office 365 -Microsoft 365 A5 for Faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,POWER_VIRTUAL_AGENTS_O365_P3,ded3d325-1bdc-453e-8432-5bac26d7a014,Power Virtual Agents for Office 365 -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CDS_O365_P3,afa73018-811e-46e9-988f-f75d2b1b8430,Common Data Service for Teams +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,LOCKBOX_ENTERPRISE,9f431833-0334-42de-a7dc-70aa40db46db,Customer Lockbox +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CustomerLockboxA_Enterprise,3ec18638-bd4c-4d3b-8905-479ed636b83e,Customer Lockbox (A) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_Exchange,cd31b152-6326-4d1b-ae1b-997b625182e6,Data Classification in Microsoft 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMON_DEFENDER_PLATFORM_FOR_OFFICE,a312bdeb-1e21-40d0-84b1-0e73f128144f,Defender Platform for Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCHANGE_S_ENTERPRISE,efb87545-963c-4e0d-99df-69c6916d9eb0,Exchange Online (Plan 2) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,GRAPH_CONNECTORS_SEARCH_INDEX,a6520331-d7d4-4276-95f5-15c0933bc757,Graph Connectors Search with Index +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Content_Explorer,d9fa6af4-e046-4c89-9226-729a0786685d,Information Protection and Governance Analytics - Premium +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ContentExplorer_Standard,2b815d45-56e4-4e3a-b65c-66cb9175b560,Information Protection and Governance Analytics – Standard +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_CLP2,efb0351d-3b08-4503-993d-383af8de41e3,Information Protection for Office 365 - Premium +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MIP_S_CLP1,5136a095-5cf0-4aff-bec3-e84448b38ea5,Information Protection for Office 365 - Standard +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,M365_ADVANCED_AUDITING,2f442157-a11c-46b9-ae5b-6e39ff4e5849,Microsoft 365 Advanced Auditing +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,OFFICESUBSCRIPTION,43de0ff5-c92c-492b-9116-175376d08c38,Microsoft 365 Apps for enterprise +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,M365_AUDIT_PLATFORM,f6de4823-28fa-440b-b886-4783fa86ddba,Microsoft 365 Audit Platform +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_COMMUNICATION_COMPLIANCE,a413a9ff-720c-4822-98ef-2f37c2a21f4c,Microsoft 365 Communication Compliance +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MTP,bf28f719-7844-4079-9c78-c1307898e192,Microsoft 365 Defender +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFTBOOKINGS,199a5c09-e0ca-4e37-8f7c-b05d533e1ea2,Microsoft Bookings +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CLIPCHAMP,a1ace008-72f3-4ea0-8dac-33b3a23a2472,Microsoft Clipchamp +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMUNICATIONS_DLP,6dc145d6-95dd-4191-b9c3-185575ee6f6b,Microsoft Communications DLP +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,CUSTOMER_KEY,6db1f1db-2b46-403f-be40-e39395f08dbb,Microsoft Customer Key +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ATP_ENTERPRISE,f20fedf3-f3c3-43c3-8267-2bfdd51c0939,Microsoft Defender for Office 365 (Plan 1) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,THREAT_INTELLIGENCE,8e0c0a52-6a6c-4d40-8370-dd62790dcd70,Microsoft Defender for Office 365 (Plan 2) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCEL_PREMIUM,531ee2f8-b1cb-453b-9c21-d2180d014ca5,Microsoft Excel Advanced Analytics +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,OFFICE_FORMS_PLAN_3,96c1e14a-ef43-418d-b115-9636cdaa8eed,Microsoft Forms (Plan 3) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INFO_GOVERNANCE,e26c2fcc-ab91-4a61-b35c-03cdc8dddf66,Microsoft Information Governance +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INSIDER_RISK,d587c7a3-bda9-4f99-8776-9bcf59c84f75,Microsoft Insider Risk Management +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INSIDER_RISK_MANAGEMENT,9d0c4ee5-e4a1-4625-ab39-d82b619b1a34,Microsoft Insider Risk Management - Exchange +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,KAIZALA_STANDALONE,0898bdbb-73b0-471a-81e5-20f1fe4dd66e,Microsoft Kaizala Pro +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_LOOP,c4b8c31a-fb44-4c65-9837-a21f55fcabda,Microsoft Loop +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ML_CLASSIFICATION,d2d51368-76c9-4317-ada2-a12c004c432f,Microsoft ML-Based Classification +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EXCHANGE_ANALYTICS,34c0d7a0-a70f-4668-9238-47f9fc208882,Microsoft MyAnalytics (Full) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RECORDS_MANAGEMENT,65cc641f-cccd-4643-97e0-a17e3045e541,Microsoft Records Management +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFT_SEARCH,94065c59-bc8e-4e8b-89e5-5138d471eaff,Microsoft Search +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Deskless,8c7d2df8-86f0-4902-b2ed-a0458298f3b3,Microsoft StaffHub +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,STREAM_O365_E5,6c6042f5-6f01-4d67-b8c1-eb99d36eed3e,Microsoft Stream for Office 365 E5 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,TEAMS1,57ff2da0-773e-42df-b2af-ffb7a2317929,Microsoft Teams +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MINECRAFT_EDUCATION_EDITION,4c246bbc-f513-4311-beff-eba54c353256,Minecraft Education Edition +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_O365,882e1d05-acd1-4ccb-8708-6ee03664b117,Mobile Device Management for Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Nucleus,db4d623d-b514-490b-b7ef-8885eee514de,Nucleus +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,EQUIVIO_ANALYTICS,4de31727-a228-4ec3-a5bf-8e45b5ca48cc,Office 365 Advanced eDiscovery +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ADALLOM_S_O365,8c098270-9dd4-4350-9b30-ba4703f3b36b,Office 365 Cloud App Security +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PAM_ENTERPRISE,b1188c4c-1b36-4018-b48b-ee07604f6feb,Office 365 Privileged Access Management +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SAFEDOCS,bf6f5520-59e3-4f82-974b-7dbbc4fd27c7,Office 365 SafeDocs +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SHAREPOINTWAC_EDU,e03c7e47-402c-463c-ab25-949079bedb21,Office for the Web for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,POWERAPPS_O365_P3,9c0dab89-a30c-4117-86e7-97bda240acd2,Power Apps for Office 365 (Plan 3) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,BI_AZURE_P2,70d33638-9c74-4d01-bfd3-562de28bd4ba,Power BI Pro +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PREMIUM_ENCRYPTION,617b097b-4b93-4ede-83de-5f075bb5fb2f,Premium Encryption in Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PROJECT_O365_P3,b21a6b06-1988-436e-a07b-51ec6d9f52ad,Project for Office (Plan E5) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,PURVIEW_DISCOVERY,c948ea65-2053-4a5a-8a62-9eaaaf11b522,Purview Discovery +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Bing_Chat_Enterprise,0d0c0d31-fae7-41f2-b909-eaf4d7f26dba,RETIRED - Commercial data protection for Microsoft Copilot +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,COMMUNICATIONS_COMPLIANCE,41fcdd7d-4733-4863-9cf4-c65b83ce2df4,RETIRED - Microsoft Communications Compliance +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,DATA_INVESTIGATIONS,46129a58-a698-46f0-aa5b-17f6586297d9,Retired - Microsoft Data Investigations +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SCHOOL_DATA_SYNC_P2,500b6a2a-7a50-4f40-b5f9-160e5b8c2f48,School Data Sync (Plan 2) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SHAREPOINTENTERPRISE_EDU,63038b2c-28d0-45f6-bc36-33062963b498,SharePoint (Plan 2) for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,SWAY,a23b959c-7ce8-4e57-9140-b90eb88a9e97,Sway +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,BPOS_S_TODO_3,3fb82609-8c27-4f7b-bd51-30634711ee67,To-Do (Plan 3) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,VIVA_LEARNING_SEEDED,b76fb638-6ba6-402a-b9f9-83d28acb3d86,Viva Learning Seeded +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WHITEBOARD_PLAN3,4a51bca5-1eff-43f5-878c-177680f191af,Whiteboard (Plan 3) +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WINDEFATP,871d91ec-ec1a-452b-a83f-bd76c7d770ef,Microsoft Defender for Endpoint +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MICROSOFTENDPOINTDLP,64bfac92-2b17-4482-b5e5-a0304429de3e,Microsoft Endpoint DLP +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,UNIVERSAL_PRINT_01,795f6fe0-cc4d-4773-b050-5dde4dc704c9,Universal Print +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Virtualization Rights for Windows 10 (E3/E5+VDA),e7c91390-7625-45be-94e0-e16907e03118,Windows 10/11 Enterprise +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,WINDOWSUPDATEFORBUSINESS_DEPLOYMENTSERVICE,7bf960f6-2cd9-443a-8046-5dbff9558365,Windows Update for Business Deployment Service +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_PREMIUM,6c57d4b6-3b23-47a5-9bc9-69f17b4947b3,Azure Information Protection Premium P1 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,RMS_S_PREMIUM2,5689bec4-755d-4753-8b61-40975025187c,Azure Information Protection Premium P2 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,DYN365_CDS_O365_P3,28b0fa46-c39a-4188-89e2-58e979a6b014,Common Data Service +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,Intune_ServiceNow,3eeb8536-fecf-41bf-a3f8-d6f17a9f3efc,Intune ServiceNow Integration +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,MFA_PREMIUM,8a256a2b-b617-496d-b51b-e76466e88db0,Microsoft Azure Multi-Factor Authentication +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ADALLOM_S_STANDALONE,2e2ddb96-6af9-4b1d-a3f0-d6ecfd22edb2,Microsoft Defender for Cloud Apps +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,ATA,14ab5db5-e6c4-4b20-b4bc-13e36fd2227f,Microsoft Defender for Identity +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,AAD_PREMIUM_P2,eec0eb4f-6444-4f95-aba0-50c24d67f998,Microsoft Entra ID P2 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune Plan 1 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune Plan 1 for Education +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,FLOW_O365_P3,07699545-9485-468e-95b6-2fca3738be01,Power Automate for Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,POWER_VIRTUAL_AGENTS_O365_P3,ded3d325-1bdc-453e-8432-5bac26d7a014,Power Virtual Agents for Office 365 +Microsoft 365 A5 for faculty,M365EDU_A5_FACULTY,e97c048c-37a4-45fb-ab50-922fbf07a370,REMOTE_HELP,a4c6cf29-1168-4076-ba5c-e8fe0e62b17e,Remote help +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,CDS_O365_P3,afa73018-811e-46e9-988f-f75d2b1b8430,Common Data Service for Teams Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,LOCKBOX_ENTERPRISE,9f431833-0334-42de-a7dc-70aa40db46db,Customer Lockbox +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,CustomerLockboxA_Enterprise,3ec18638-bd4c-4d3b-8905-479ed636b83e,Customer Lockbox (A) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MIP_S_Exchange,cd31b152-6326-4d1b-ae1b-997b625182e6,Data Classification in Microsoft 365 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,COMMON_DEFENDER_PLATFORM_FOR_OFFICE,a312bdeb-1e21-40d0-84b1-0e73f128144f,Defender Platform for Office 365 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,EXCHANGE_S_ENTERPRISE,efb87545-963c-4e0d-99df-69c6916d9eb0,Exchange Online (Plan 2) +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,GRAPH_CONNECTORS_SEARCH_INDEX,a6520331-d7d4-4276-95f5-15c0933bc757,Graph Connectors Search with Index Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,Content_Explorer,d9fa6af4-e046-4c89-9226-729a0786685d,Information Protection and Governance Analytics - Premium Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ContentExplorer_Standard,2b815d45-56e4-4e3a-b65c-66cb9175b560,Information Protection and Governance Analytics – Standard Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MIP_S_CLP2,efb0351d-3b08-4503-993d-383af8de41e3,Information Protection for Office 365 - Premium Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MIP_S_CLP1,5136a095-5cf0-4aff-bec3-e84448b38ea5,Information Protection for Office 365 - Standard Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,M365_ADVANCED_AUDITING,2f442157-a11c-46b9-ae5b-6e39ff4e5849,Microsoft 365 Advanced Auditing -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,OFFICESUBSCRIPTION,43de0ff5-c92c-492b-9116-175376d08c38,Microsoft 365 Apps for Enterprise +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,OFFICESUBSCRIPTION,43de0ff5-c92c-492b-9116-175376d08c38,Microsoft 365 Apps for enterprise Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,M365_AUDIT_PLATFORM,f6de4823-28fa-440b-b886-4783fa86ddba,Microsoft 365 Audit Platform Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MICROSOFT_COMMUNICATION_COMPLIANCE,a413a9ff-720c-4822-98ef-2f37c2a21f4c,Microsoft 365 Communication Compliance Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MTP,bf28f719-7844-4079-9c78-c1307898e192,Microsoft 365 Defender +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MICROSOFTBOOKINGS,199a5c09-e0ca-4e37-8f7c-b05d533e1ea2,Microsoft Bookings +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,CLIPCHAMP,a1ace008-72f3-4ea0-8dac-33b3a23a2472,Microsoft Clipchamp Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,COMMUNICATIONS_DLP,6dc145d6-95dd-4191-b9c3-185575ee6f6b,Microsoft Communications DLP Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,CUSTOMER_KEY,6db1f1db-2b46-403f-be40-e39395f08dbb,Microsoft Customer Key -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,DATA_INVESTIGATIONS,46129a58-a698-46f0-aa5b-17f6586297d9,Microsoft Data Investigations Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ATP_ENTERPRISE,f20fedf3-f3c3-43c3-8267-2bfdd51c0939,Microsoft Defender for Office 365 (Plan 1) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,THREAT_INTELLIGENCE,8e0c0a52-6a6c-4d40-8370-dd62790dcd70,Microsoft Defender for Office 365 (Plan 2) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,EXCEL_PREMIUM,531ee2f8-b1cb-453b-9c21-d2180d014ca5,Microsoft Excel Advanced Analytics Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,OFFICE_FORMS_PLAN_3,96c1e14a-ef43-418d-b115-9636cdaa8eed,Microsoft Forms (Plan 3) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INFO_GOVERNANCE,e26c2fcc-ab91-4a61-b35c-03cdc8dddf66,Microsoft Information Governance Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INSIDER_RISK,d587c7a3-bda9-4f99-8776-9bcf59c84f75,Microsoft Insider Risk Management +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INSIDER_RISK_MANAGEMENT,9d0c4ee5-e4a1-4625-ab39-d82b619b1a34,Microsoft Insider Risk Management - Exchange Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,KAIZALA_STANDALONE,0898bdbb-73b0-471a-81e5-20f1fe4dd66e,Microsoft Kaizala Pro +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MICROSOFT_LOOP,c4b8c31a-fb44-4c65-9837-a21f55fcabda,Microsoft Loop Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ML_CLASSIFICATION,d2d51368-76c9-4317-ada2-a12c004c432f,Microsoft ML-Based Classification Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,EXCHANGE_ANALYTICS,34c0d7a0-a70f-4668-9238-47f9fc208882,Microsoft MyAnalytics (Full) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner @@ -1091,8 +1117,10 @@ Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,BI_AZURE_P2,70d33638-9c74-4d01-bfd3-562de28bd4ba,Power BI Pro Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,PREMIUM_ENCRYPTION,617b097b-4b93-4ede-83de-5f075bb5fb2f,Premium Encryption in Office 365 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,PROJECT_O365_P3,b21a6b06-1988-436e-a07b-51ec6d9f52ad,Project for Office (Plan E5) +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,PURVIEW_DISCOVERY,c948ea65-2053-4a5a-8a62-9eaaaf11b522,Purview Discovery +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,Bing_Chat_Enterprise,0d0c0d31-fae7-41f2-b909-eaf4d7f26dba,RETIRED - Commercial data protection for Microsoft Copilot Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,COMMUNICATIONS_COMPLIANCE,41fcdd7d-4733-4863-9cf4-c65b83ce2df4,RETIRED - Microsoft Communications Compliance -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INSIDER_RISK_MANAGEMENT,9d0c4ee5-e4a1-4625-ab39-d82b619b1a34,RETIRED - Microsoft Insider Risk Management +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,DATA_INVESTIGATIONS,46129a58-a698-46f0-aa5b-17f6586297d9,Retired - Microsoft Data Investigations Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,SCHOOL_DATA_SYNC_P2,500b6a2a-7a50-4f40-b5f9-160e5b8c2f48,School Data Sync (Plan 2) Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,SHAREPOINTENTERPRISE_EDU,63038b2c-28d0-45f6-bc36-33062963b498,SharePoint (Plan 2) for Education Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) @@ -1105,18 +1133,20 @@ Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,UNIVERSAL_PRINT_01,795f6fe0-cc4d-4773-b050-5dde4dc704c9,Universal Print Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,Virtualization Rights for Windows 10 (E3/E5+VDA),e7c91390-7625-45be-94e0-e16907e03118,Windows 10/11 Enterprise Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,WINDOWSUPDATEFORBUSINESS_DEPLOYMENTSERVICE,7bf960f6-2cd9-443a-8046-5dbff9558365,Windows Update for Business Deployment Service -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_PREMIUM_P2,eec0eb4f-6444-4f95-aba0-50c24d67f998,Microsoft Entra ID P2 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,RMS_S_PREMIUM,6c57d4b6-3b23-47a5-9bc9-69f17b4947b3,Azure Information Protection Premium P1 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,RMS_S_PREMIUM2,5689bec4-755d-4753-8b61-40975025187c,Azure Information Protection Premium P2 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,DYN365_CDS_O365_P3,28b0fa46-c39a-4188-89e2-58e979a6b014,Common Data Service +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,Intune_ServiceNow,3eeb8536-fecf-41bf-a3f8-d6f17a9f3efc,Intune ServiceNow Integration Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,MFA_PREMIUM,8a256a2b-b617-496d-b51b-e76466e88db0,Microsoft Azure Multi-Factor Authentication Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ADALLOM_S_STANDALONE,2e2ddb96-6af9-4b1d-a3f0-d6ecfd22edb2,Microsoft Defender for Cloud Apps Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,ATA,14ab5db5-e6c4-4b20-b4bc-13e36fd2227f,Microsoft Defender for Identity -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune -Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune for Education +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,AAD_PREMIUM_P2,eec0eb4f-6444-4f95-aba0-50c24d67f998,Microsoft Entra ID P2 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune Plan 1 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,INTUNE_EDU,da24caf9-af8e-485c-b7c8-e73336da2693,Microsoft Intune Plan 1 for Education Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,FLOW_O365_P3,07699545-9485-468e-95b6-2fca3738be01,Power Automate for Office 365 Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,POWER_VIRTUAL_AGENTS_O365_P3,ded3d325-1bdc-453e-8432-5bac26d7a014,Power Virtual Agents for Office 365 +Microsoft 365 A5 for Students,M365EDU_A5_STUDENT,46c119d4-0379-4a9d-85e4-97c66d3f909e,REMOTE_HELP,a4c6cf29-1168-4076-ba5c-e8fe0e62b17e,Remote help Microsoft 365 A5 for students use benefit,M365EDU_A5_STUUSEBNFT,31d57bc7-3a05-4867-ab53-97a17835a411,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education Microsoft 365 A5 for students use benefit,M365EDU_A5_STUUSEBNFT,31d57bc7-3a05-4867-ab53-97a17835a411,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management Microsoft 365 A5 for students use benefit,M365EDU_A5_STUUSEBNFT,31d57bc7-3a05-4867-ab53-97a17835a411,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics @@ -3633,13 +3663,19 @@ Microsoft Dynamics CRM Online,CRMSTANDARD,d17b27af-3f49-4822-99f9-56a661538792,M Microsoft Dynamics CRM Online,CRMSTANDARD,d17b27af-3f49-4822-99f9-56a661538792,NBPROFESSIONALFORCRM,3e58e97c-9abe-ebab-cd5f-d543d1529634,MICROSOFT SOCIAL ENGAGEMENT PROFESSIONAL - ELIGIBILITY CRITERIA APPLY Microsoft Dynamics CRM Online,CRMSTANDARD,d17b27af-3f49-4822-99f9-56a661538792,POWERAPPS_DYN_APPS,874fc546-6efe-4d22-90b8-5c4e7aa59f4b,POWERAPPS FOR DYNAMICS 365 Microsoft Entra ID Governance,Microsoft_Entra_ID_Governance,cf6b0d46-4093-4546-a0ab-0b1546dcc10e,Entra_Identity_Governance,e866a266-3cff-43a3-acca-0c90a7e00c8b,Entra Identity Governance +Microsoft Entra Suite Add-on for Microsoft Entra ID P2,Microsoft_Entra_Suite_Step_Up_for_Microsoft_Entra_ID_P2,2ef3064c-c95c-426c-96dd-9ffeaa2f2c37,Entra_Premium_Internet_Access,8d23cb83-ab07-418f-8517-d7aca77307dc,Microsoft Entra Internet Access +Microsoft Entra Suite Add-on for Microsoft Entra ID P2,Microsoft_Entra_Suite_Step_Up_for_Microsoft_Entra_ID_P2,2ef3064c-c95c-426c-96dd-9ffeaa2f2c37,Entra_Premium_Private_Access,f057aab1-b184-49b2-85c0-881b02a405c5,Microsoft Entra Private Access +Microsoft Entra Suite Add-on for Microsoft Entra ID P2,Microsoft_Entra_Suite_Step_Up_for_Microsoft_Entra_ID_P2,2ef3064c-c95c-426c-96dd-9ffeaa2f2c37,Verifiable_Credentials_Service_Request,aae826b7-14cd-4691-8178-2b312f7072ea,Verifiable Credentials Service Request +Microsoft Entra Suite Add-on for Microsoft Entra ID P2,Microsoft_Entra_Suite_Step_Up_for_Microsoft_Entra_ID_P2,2ef3064c-c95c-426c-96dd-9ffeaa2f2c37,Entra_Identity_Governance,e866a266-3cff-43a3-acca-0c90a7e00c8b,Entra Identity Governance Microsoft Fabric (Free),POWER_BI_STANDARD,a403ebcc-fae0-4ca2-8c8c-7a907fd6c235,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Microsoft Fabric (Free),POWER_BI_STANDARD,a403ebcc-fae0-4ca2-8c8c-7a907fd6c235,BI_AZURE_P0,2049e525-b859-401b-b2a0-e0a31c4b1fe4,Power BI (free) +Microsoft Fabric (Free),POWER_BI_STANDARD,a403ebcc-fae0-4ca2-8c8c-7a907fd6c235,PURVIEW_DISCOVERY,c948ea65-2053-4a5a-8a62-9eaaaf11b522,Purview Discovery Microsoft Fabric (Free) for faculty,POWER_BI_STANDARD_FACULTY,ade29b5f-397e-4eb9-a287-0344bd46c68d,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,EXCHANGE_S_FOUNDATION Microsoft Fabric (Free) for faculty,POWER_BI_STANDARD_FACULTY,ade29b5f-397e-4eb9-a287-0344bd46c68d,BI_AZURE_P0,2049e525-b859-401b-b2a0-e0a31c4b1fe4,BI_AZURE_P0 Microsoft Fabric (Free) for student,POWER_BI_STANDARD_STUDENT,bdcaf6aa-04c1-4b8f-b64e-6e3bd505ac64,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,EXCHANGE_S_FOUNDATION Microsoft Fabric (Free) for student,POWER_BI_STANDARD_STUDENT,bdcaf6aa-04c1-4b8f-b64e-6e3bd505ac64,BI_AZURE_P0,2049e525-b859-401b-b2a0-e0a31c4b1fe4,BI_AZURE_P0 Microsoft Imagine Academy,IT_ACADEMY_AD,ba9a34de-4489-469d-879c-0f0f145321cd,IT_ACADEMY_AD,d736def0-1fde-43f0-a5be-e3f8b2de6e41,MS IMAGINE ACADEMY +Microsoft Intune Advanced Analytics,Microsoft_Intune_Advanced_Analytics,5e36d0d4-e9e5-4052-aba0-0257465c9b86,Intune_AdvancedEA,2a4baa0e-5e99-4c38-b1f2-6864960f1bd1,Microsoft Intune Advanced Analytics Microsoft Intune Device,INTUNE_A_D,2b317a4a-77a6-4188-9437-b68a77b4e2c6,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Microsoft Intune Device,INTUNE_A_D,2b317a4a-77a6-4188-9437-b68a77b4e2c6,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune Microsoft Intune Device for Government,INTUNE_A_D_GOV,2c21e77a-e0d6-4570-b38a-7ff2dc17d2ca,EXCHANGE_S_FOUNDATION_GOV,922ba911-5694-4e99-a794-73aed9bfeec8,Exchange Foundation for Government @@ -3696,6 +3732,10 @@ Microsoft Stream Storage Add-On (500 GB),STREAM_STORAGE,9bd7c846-9556-4453-a542- Microsoft Sustainability Manager Premium,Microsoft_Sustainability_Manager_Premium,aecb477b-2f56-4e38-b711-b752c24fc19b,CDS_CLOUD_FOR_SUSTAINABILITY_PLUS,ba80223c-e515-4642-a838-3e7d66f70cb6,Common Data Services for Cloud for Sustainability Plus Microsoft Sustainability Manager Premium,Microsoft_Sustainability_Manager_Premium,aecb477b-2f56-4e38-b711-b752c24fc19b,MCS_BIZAPPS_CLOUD_FOR_SUSTAINABILITY_PLUS,ed29ae92-ff5f-4446-8460-83c54d0e7088,MCS - BizApps Cloud for Sustainability Plus Microsoft Sustainability Manager Premium,Microsoft_Sustainability_Manager_Premium,aecb477b-2f56-4e38-b711-b752c24fc19b,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +Microsoft Sustainability Manager Premium USL Plus,MICROSOFT_SUSTAINABILITY_MANAGER_PREMIUM_USL_ADDON,9d576ffb-dd32-4c33-91ee-91625b61424a,MCS_BIZAPPS_CLOUD_FOR_SUSTAINABILITY_USL_PLUS,beaf5b5c-d11c-4417-b5cb-cd9f9e6719b0,MCS - BizApps Cloud for Sustainability USL Plus +Microsoft Sustainability Manager Premium USL Plus,MICROSOFT_SUSTAINABILITY_MANAGER_PREMIUM_USL_ADDON,9d576ffb-dd32-4c33-91ee-91625b61424a,POWER_APPS_FOR_MCS_USL_PLUS,c5502fe7-406d-442a-827f-4948b821ba08,Power Apps for Cloud for Sustainability USL Plus +Microsoft Sustainability Manager Premium USL Plus,MICROSOFT_SUSTAINABILITY_MANAGER_PREMIUM_USL_ADDON,9d576ffb-dd32-4c33-91ee-91625b61424a,POWER_AUTOMATE_FOR_MCS_USL_PLUS,1c22bb50-96fb-49e5-baa6-195cab19eee2,Power Automate for Cloud for Sustainability USL Plus +Microsoft Sustainability Manager Premium USL Plus,MICROSOFT_SUSTAINABILITY_MANAGER_PREMIUM_USL_ADDON,9d576ffb-dd32-4c33-91ee-91625b61424a,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Microsoft Sustainability Manager USL Essentials,Microsoft_Cloud_for_Sustainability_USL,ece037b4-a52b-4cf8-93ea-649e5d83767a,MCS_BizApps_Cloud_for_Sustainability_USL,c46c42af-d654-4385-8c85-29a84f3dfb22,MCS - BizApps - Cloud for Sustainability USL Microsoft Sustainability Manager USL Essentials,Microsoft_Cloud_for_Sustainability_USL,ece037b4-a52b-4cf8-93ea-649e5d83767a,POWER_APPS_FOR_MCS_USL,5ffd371c-037a-41a2-98a3-6452f8c5de17,Power Apps for Cloud for Sustainability USL Microsoft Sustainability Manager USL Essentials,Microsoft_Cloud_for_Sustainability_USL,ece037b4-a52b-4cf8-93ea-649e5d83767a,POWER_AUTOMATE_FOR_MCS_USL,ccbe468e-7973-442c-8ec4-5fbe16438711,Power Automate for Cloud for Sustainability USL @@ -3808,18 +3848,20 @@ Microsoft Teams Rooms Pro,Microsoft_Teams_Rooms_Pro,4cde982a-ede4-4409-9ae6-b003 Microsoft Teams Rooms Pro,Microsoft_Teams_Rooms_Pro,4cde982a-ede4-4409-9ae6-b003453c8ea6,TEAMS1,57ff2da0-773e-42df-b2af-ffb7a2317929,Microsoft Teams Microsoft Teams Rooms Pro,Microsoft_Teams_Rooms_Pro,4cde982a-ede4-4409-9ae6-b003453c8ea6,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) Microsoft Teams Rooms Pro,Microsoft_Teams_Rooms_Pro,4cde982a-ede4-4409-9ae6-b003453c8ea6,WHITEBOARD_PLAN3,4a51bca5-1eff-43f5-878c-177680f191af,Whiteboard (Plan 3) -Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education +Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,TEAMS1,57ff2da0-773e-42df-b2af-ffb7a2317929,Microsoft Teams Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,MTRProManagement,ecc74eae-eeb7-4ad5-9c88-e8b2bfca75b8,Microsoft Teams Rooms Pro Management Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) +Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,Teams_Rooms_Pro,0374d34c-6be4-4dbb-b3f0-26105db0b28a,Teams Rooms Pro Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,Teams_Room_Basic,8081ca9c-188c-4b49-a8e5-c23b5e9463a8,Teams Rooms Test 1 Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,Teams_Room_Pro,ec17f317-f4bc-451e-b2da-0167e5c260f9,Teams Rooms Test 2 Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,WHITEBOARD_PLAN3,4a51bca5-1eff-43f5-878c-177680f191af,Whiteboard (Plan 3) Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,WINDEFATP,871d91ec-ec1a-452b-a83f-bd76c7d770ef,Microsoft Defender for Endpoint Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,AAD_PREMIUM,41781fb2-bc02-4b7c-bd55-b576c07bb09d,Microsoft Entra ID P1 Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,INTUNE_A,c1ec4a95-1f05-45b3-a911-aa3fa01094f5,Microsoft Intune Plan 1 +Microsoft Teams Rooms Pro for EDU,Microsoft_Teams_Rooms_Pro_FAC,c25e2b36-e161-4946-bef2-69239729f690,SPECIALTY_DEVICES,cfce7ae3-4b41-4438-999c-c0e91f3b7fb9,Specialty devices Microsoft Teams Rooms Pro for GCC,Microsoft_Teams_Rooms_Pro_GCC,31ecb341-2a17-483e-9140-c473006d1e1a,MCOMEETADV_GOV,f544b08d-1645-4287-82de-8d91f37c02a1,Microsoft 365 Audio Conferencing for Government Microsoft Teams Rooms Pro for GCC,Microsoft_Teams_Rooms_Pro_GCC,31ecb341-2a17-483e-9140-c473006d1e1a,MCOEV_GOV,db23fce2-a974-42ef-9002-d78dd42a0f22,Microsoft 365 Phone System for Government Microsoft Teams Rooms Pro for GCC,Microsoft_Teams_Rooms_Pro_GCC,31ecb341-2a17-483e-9140-c473006d1e1a,TEAMS_GOV,304767db-7d23-49e8-a945-4a7eb65f9f28,Microsoft Teams for Government @@ -3914,14 +3956,14 @@ Office 365 Multi-Geo Capabilities,OFFICE365_MULTIGEO,84951599-62b7-46f3-9c9d-305 Office 365 Multi-Geo Capabilities,OFFICE365_MULTIGEO,84951599-62b7-46f3-9c9d-30551b2ad607,TEAMSMULTIGEO,41eda15d-6b52-453b-906f-bc4a5b25a26b,Teams Multi-Geo Nonprofit Portal,NONPROFIT_PORTAL,aa2695c9-8d59-4800-9dc8-12e01f1735af,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation Nonprofit Portal,NONPROFIT_PORTAL,aa2695c9-8d59-4800-9dc8-12e01f1735af,NONPROFIT_PORTAL,7dbc2d88-20e2-4eb6-b065-4510b38d6eb2,Nonprofit Portal -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service - O365 P1 +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,EXCHANGE_S_STANDARD,9aaf7827-d63c-4b61-89c3-182f06f82e5c,Exchange Online (Plan 1) Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Microsoft Microsoft Entra Rights +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,OFFICE_FORMS_PLAN_2,9b5de886-f035-4ff2-b3d8-c9127bea3620,Microsoft Forms (Plan 2) -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,KAIZALA_O365_P2,54fc630f-5a40-48ee-8965-af0503c1386e,Microsoft Kaizala Pro Plan 2 +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,KAIZALA_O365_P2,54fc630f-5a40-48ee-8965-af0503c1386e,Microsoft Kaizala Pro Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,MICROSOFT_SEARCH,94065c59-bc8e-4e8b-89e5-5138d471eaff,Microsoft Search Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,Deskless,8c7d2df8-86f0-4902-b2ed-a0458298f3b3,Microsoft StaffHub @@ -3931,9 +3973,8 @@ Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c897 Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,Nucleus,db4d623d-b514-490b-b7ef-8885eee514de,Nucleus Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,SHAREPOINTWAC_EDU,e03c7e47-402c-463c-ab25-949079bedb21,Office for the Web for Education Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,OFFICEMOBILE_SUBSCRIPTION,c63d4d19-e8cb-460e-b37c-4d6c34603745,Office Mobile Apps for Office 365 -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 -Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,PROJECT_O365_P1,a55dfd10-0864-46d9-a3cd-da5991a3e0e2,Project for Office (Plan E1) +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,Bing_Chat_Enterprise,0d0c0d31-fae7-41f2-b909-eaf4d7f26dba,RETIRED - Commercial data protection for Microsoft Copilot Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,SCHOOL_DATA_SYNC_P1,c33802dd-1b50-4b9a-8bb9-f13d2cdeadac,School Data Sync (Plan 1) Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,SHAREPOINTSTANDARD_EDU,0a4983bb-d3e5-4a09-95d8-b2d0127b3df5,SharePoint (Plan 1) for Education Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) @@ -3942,6 +3983,9 @@ Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c897 Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,VIVA_LEARNING_SEEDED,b76fb638-6ba6-402a-b9f9-83d28acb3d86,Viva Learning Seeded Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,WHITEBOARD_PLAN1,b8afc642-032e-4de5-8c0a-507a7bba7e5d,Whiteboard (Plan 1) Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 +Office 365 A1 for faculty,STANDARDWOFFPACK_FACULTY,94763226-9b3c-4e75-a931-5c89701abe66,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service - O365 P1 Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics @@ -3969,14 +4013,14 @@ Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-89 Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,VIVA_LEARNING_SEEDED,b76fb638-6ba6-402a-b9f9-83d28acb3d86,Viva Learning Seeded Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,WHITEBOARD_PLAN1,b8afc642-032e-4de5-8c0a-507a7bba7e5d,Whiteboard (Plan 1) Office 365 A1 Plus for faculty,STANDARDWOFFPACK_IW_FACULTY,78e66a63-337a-4a9a-8959-41c6654dfb56,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service - O365 P1 +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Azure Active Directory Basic for Education +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Azure Rights Management Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,EXCHANGE_S_STANDARD,9aaf7827-d63c-4b61-89c3-182f06f82e5c,Exchange Online (Plan 1) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,INFORMATION_BARRIERS,c4801e8a-cb58-4c35-aca6-f2dcc106f287,Information Barriers -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,RMS_S_ENTERPRISE,bea4c11e-220a-4e6d-8eb8-8ea15d019f90,Microsoft Microsoft Entra Rights +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,M365_LIGHTHOUSE_CUSTOMER_PLAN1,6f23d6a9-adbf-481c-8538-b4c095654487,Microsoft 365 Lighthouse (Plan 1) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,OFFICE_FORMS_PLAN_2,9b5de886-f035-4ff2-b3d8-c9127bea3620,Microsoft Forms (Plan 2) -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,KAIZALA_O365_P2,54fc630f-5a40-48ee-8965-af0503c1386e,Microsoft Kaizala Pro Plan 2 +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,KAIZALA_O365_P2,54fc630f-5a40-48ee-8965-af0503c1386e,Microsoft Kaizala Pro Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,PROJECTWORKMANAGEMENT,b737dad2-2f6c-4c65-90e3-ca563267e8b9,Microsoft Planner Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,MICROSOFT_SEARCH,94065c59-bc8e-4e8b-89e5-5138d471eaff,Microsoft Search Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,Deskless,8c7d2df8-86f0-4902-b2ed-a0458298f3b3,Microsoft StaffHub @@ -3985,9 +4029,8 @@ Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4 Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,INTUNE_O365,882e1d05-acd1-4ccb-8708-6ee03664b117,Mobile Device Management for Office 365 Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,SHAREPOINTWAC_EDU,e03c7e47-402c-463c-ab25-949079bedb21,Office for the Web for Education Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,OFFICEMOBILE_SUBSCRIPTION,c63d4d19-e8cb-460e-b37c-4d6c34603745,Office Mobile Apps for Office 365 -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 -Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,PROJECT_O365_P1,a55dfd10-0864-46d9-a3cd-da5991a3e0e2,Project for Office (Plan E1) +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,Bing_Chat_Enterprise,0d0c0d31-fae7-41f2-b909-eaf4d7f26dba,RETIRED - Commercial data protection for Microsoft Copilot Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,SCHOOL_DATA_SYNC_P1,c33802dd-1b50-4b9a-8bb9-f13d2cdeadac,School Data Sync (Plan 1) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,SHAREPOINTSTANDARD_EDU,0a4983bb-d3e5-4a09-95d8-b2d0127b3df5,SharePoint (Plan 1) for Education Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,MCOSTANDARD,0feaeb32-d00e-4d66-bd5a-43b5b83db82c,Skype for Business Online (Plan 2) @@ -3995,6 +4038,9 @@ Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4 Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,BPOS_S_TODO_2,c87f142c-d1e9-4363-8630-aaea9c4d9ae5,To-Do (Plan 2) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,WHITEBOARD_PLAN1,b8afc642-032e-4de5-8c0a-507a7bba7e5d,Whiteboard (Plan 1) Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,YAMMER_EDU,2078e8df-cff6-4290-98cb-5408261a760a,Yammer for Academic +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,POWERAPPS_O365_P2,c68f8d98-5534-41c8-bf36-22fa496fa792,Power Apps for Office 365 +Office 365 A1 for students,STANDARDWOFFPACK_STUDENT,314c4481-f395-4525-be8b-2ec4bb1e9d91,FLOW_O365_P2,76846ad7-7776-4c40-a281-a386362dd1b9,Power Automate for Office 365 Office 365 A1 Plus for students,STANDARDWOFFPACK_IW_STUDENT,e82ae690-a2d5-4d76-8d30-7c6e01e6022e,AAD_BASIC_EDU,1d0f309f-fdf9-4b2a-9ae7-9c48b91f1426,Microsoft Entra ID Basic for Education Office 365 A1 Plus for students,STANDARDWOFFPACK_IW_STUDENT,e82ae690-a2d5-4d76-8d30-7c6e01e6022e,DYN365_CDS_O365_P1,40b010bb-0b69-4654-ac5e-ba161433f4b4,Common Data Service - O365 P1 Office 365 A1 Plus for students,STANDARDWOFFPACK_IW_STUDENT,e82ae690-a2d5-4d76-8d30-7c6e01e6022e,EducationAnalyticsP1,a9b86446-fa4e-498f-a92a-41b447e03337,Education Analytics @@ -5059,8 +5105,11 @@ Power Apps Per User BD Only,POWERAPPS_PER_USER_BD_ONLY,2ced8a00-3ed1-4295-ab7c-5 Power Apps Per User BD Only,POWERAPPS_PER_USER_BD_ONLY,2ced8a00-3ed1-4295-ab7c-57170ff28e58,CDS_ POWERAPPS_PER_USER_CUSTOM,2e8dde43-6986-479d-b179-7dbe31c31f60,CDS Power Apps Per User Custom Power Apps Per User BD Only,POWERAPPS_PER_USER_BD_ONLY,2ced8a00-3ed1-4295-ab7c-57170ff28e58,POWERAPPS_PER_USER,ea2cf03b-ac60-46ae-9c1d-eeaeb63cec86,Power Apps per User Plan Power Apps Per User BD Only,POWERAPPS_PER_USER_BD_ONLY,2ced8a00-3ed1-4295-ab7c-57170ff28e58,Flow_PowerApps_PerUser,dc789ed8-0170-4b65-a415-eb77d5bb350a,Power Automate for Power Apps per User Plan -Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,DYN365_CDS_P2,6ea4c1ef-c259-46df-bce2-943342cd3cb2,Common Data Service - P2 +Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,Power_Pages_Internal_User,60bf28f9-2b70-4522-96f7-335f5e06c941,Power Pages Internal User Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation +Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,CDSAICAPACITY_PERUSER_NEW,74d93933-6f22-436e-9441-66d205435abb,AI Builder capacity Per User add-on +Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,DYN365_CDS_P2,6ea4c1ef-c259-46df-bce2-943342cd3cb2,Common Data Service +Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,CDSAICAPACITY_PERUSER,91f50f7b-2204-4803-acac-5cf5668b8b39,DO NOT USE - AI Builder capacity Per User add-on Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,POWERAPPS_PER_USER,ea2cf03b-ac60-46ae-9c1d-eeaeb63cec86,Power Apps per User Plan Power Apps Premium,POWERAPPS_PER_USER,b30411f5-fea1-4a59-9ad9-3db7c7ead579,Flow_PowerApps_PerUser,dc789ed8-0170-4b65-a415-eb77d5bb350a,Power Automate for Power Apps per User Plan Power Apps Premium for Government,POWERAPPS_PER_USER_GCC,8e4c6baa-f2ff-4884-9c38-93785d0d7ba1,CDSAICAPACITY_PERUSER,91f50f7b-2204-4803-acac-5cf5668b8b39,AI Builder capacity Per User add-on @@ -5130,6 +5179,8 @@ Power BI Premium Per User,PBI_PREMIUM_PER_USER,c1d032e0-5619-4761-9b5c-75b6831e1 Power BI Premium Per User,PBI_PREMIUM_PER_USER,c1d032e0-5619-4761-9b5c-75b6831e1711,BI_AZURE_P3,0bf3c642-7bb5-4ccc-884e-59d09df0266c,Power BI Premium Per User Power BI Premium Per User,PBI_PREMIUM_PER_USER,c1d032e0-5619-4761-9b5c-75b6831e1711,BI_AZURE_P2,70d33638-9c74-4d01-bfd3-562de28bd4ba,Power BI Pro Power BI Premium Per User Add-On,PBI_PREMIUM_PER_USER_ADDON,de376a03-6e5b-42ec-855f-093fb50b8ca5,BI_AZURE_P3,0bf3c642-7bb5-4ccc-884e-59d09df0266c,Power BI Premium Per User +Power BI Premium Per User Add-On for Faculty,PBI_PREMIUM_PER_USER_ADDON_FACULTY,c05b235f-be75-4029-8851-6a4170758eef,BI_AZURE_P3,0bf3c642-7bb5-4ccc-884e-59d09df0266c,Power BI Premium Per User +Power BI Premium Per User Add-On for Faculty,PBI_PREMIUM_PER_USER_ADDON_FACULTY,c05b235f-be75-4029-8851-6a4170758eef,PURVIEW_DISCOVERY,c948ea65-2053-4a5a-8a62-9eaaaf11b522,Purview Discovery Power BI Premium Per User Add-On for GCC,PBI_PREMIUM_PER_USER_ADDON_CE_GCC,66024bbf-4cd4-4329-95c8-c932e2ae01a8,BI_AZURE_P3_GOV,32d15238-9a8c-46da-af3f-21fc5351d365,Power BI Premium Per User for Government Power BI Premium Per User Add-On for GCC,PBI_PREMIUM_PER_USER_ADDON_GCC,1b572d5e-1bf8-4b19-9259-f9eda31a6972,BI_AZURE_P3_GOV,32d15238-9a8c-46da-af3f-21fc5351d365,Power BI Premium Per User for Government Power BI Premium Per User Dept,PBI_PREMIUM_PER_USER_DEPT,f168a3fb-7bcf-4a27-98c3-c235ea4b78b4,EXCHANGE_S_FOUNDATION,113feb6c-3fe4-4440-bddc-54d774bf0318,Exchange Foundation @@ -5426,6 +5477,14 @@ Teams Premium (for Departments),Teams_Premium_(for_Departments),52ea0e27-ae73-49 Teams Premium (for Departments),Teams_Premium_(for_Departments),52ea0e27-ae73-4983-a08f-13561ebdb823,TEAMSPRO_VIRTUALAPPT,9104f592-f2a7-4f77-904c-ca5a5715883f,Microsoft Teams Premium Virtual Appointment Teams Premium (for Departments),Teams_Premium_(for_Departments),52ea0e27-ae73-4983-a08f-13561ebdb823,MCO_VIRTUAL_APPT,711413d0-b36e-4cd4-93db-0a50a4ab7ea3,Microsoft Teams Premium Virtual Appointments Teams Premium (for Departments),Teams_Premium_(for_Departments),52ea0e27-ae73-4983-a08f-13561ebdb823,TEAMSPRO_WEBINAR,78b58230-ec7e-4309-913c-93a45cc4735b,Microsoft Teams Premium Webinar +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,MICROSOFT_ECDN,85704d55-2e73-47ee-93b4-4b8ea14db92b,Microsoft eCDN +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_MGMT,0504111f-feb8-4a3c-992a-70280f9a2869,Microsoft Teams Premium Intelligent +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_CUST,cc8c0802-a325-43df-8cba-995d0c6cb373,Microsoft Teams Premium Personalized +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_PROTECTION,f8b44f54-18bb-46a3-9658-44ab58712968,Microsoft Teams Premium Secure +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_VIRTUALAPPT,9104f592-f2a7-4f77-904c-ca5a5715883f,Microsoft Teams Premium Virtual Appointment +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,MCO_VIRTUAL_APPT,711413d0-b36e-4cd4-93db-0a50a4ab7ea3,Microsoft Teams Premium Virtual Appointments +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,TEAMSPRO_WEBINAR,78b58230-ec7e-4309-913c-93a45cc4735b,Microsoft Teams Premium Webinar +Teams Premium for Faculty,Teams_Premium_for_Faculty,960a972f-d017-4a17-8f64-b42c8035bc7d,QUEUES_APP,ab2d4fb5-f80a-4bf1-a11d-7f1da254041b,Queues app for Microsoft Teams Teams Rooms Premium,MTR_PREM,4fb214cb-a430-4a91-9c91-4976763aa78f,MMR_P1,bdaa59a3-74fd-4137-981a-31d4f84eb8a0,Meeting Room Managed Services Teams Rooms Premium,MTR_PREM,4fb214cb-a430-4a91-9c91-4976763aa78f,MCOMEETADV,3e26ee1f-8a5f-4d52-aee2-b81ce45c8f40,Microsoft 365 Audio Conferencing Teams Rooms Premium,MTR_PREM,4fb214cb-a430-4a91-9c91-4976763aa78f,MCOEV,4828c8ec-dc2e-4779-b502-87ac9ce28ab7,Microsoft 365 Phone System diff --git a/Modules/CippExtensions/Public/PwPush/New-PwPushLink.ps1 b/Modules/CippExtensions/Public/PwPush/New-PwPushLink.ps1 index 3d2744355e60..ad58593c9676 100644 --- a/Modules/CippExtensions/Public/PwPush/New-PwPushLink.ps1 +++ b/Modules/CippExtensions/Public/PwPush/New-PwPushLink.ps1 @@ -3,9 +3,35 @@ function New-PwPushLink { Param( $Payload ) - $Table = Get-CIPPTable -TableName Extensionsconfig - $Configuration = ((Get-CIPPAzDataTableEntity @Table).config | ConvertFrom-Json).PWPush - if ($Configuration.Enabled -eq $true) { + + try { + $Table = Get-CIPPTable -TableName Extensionsconfig + $ConfigEntity = Get-CIPPAzDataTableEntity @Table + + # Check if the config entity exists and has a config property + if (-not $ConfigEntity -or [string]::IsNullOrEmpty($ConfigEntity.config)) { + return $false + } + + # Safely parse the JSON configuration + try { + $ParsedConfig = $ConfigEntity.config | ConvertFrom-Json -ErrorAction Stop + $Configuration = $ParsedConfig.PWPush + } catch { + return $false + } + + # Check if PWPush section exists in configuration + if (-not $Configuration) { + return $false + } + + # Check if PwPush is enabled + if ($Configuration.Enabled -ne $true) { + return $false + } + + # Proceed with creating the PwPush link try { Set-PwPushConfig -Configuration $Configuration $PushParams = @{ @@ -25,13 +51,15 @@ function New-PwPushLink { } } catch { $LogData = [PSCustomObject]@{ - 'Response' = $Link + 'Response' = if ($Link) { $Link } else { 'No response' } 'Exception' = Get-CippException -Exception $_ } Write-LogMessage -API PwPush -Message "Failed to create a new PwPush link: $($_.Exception.Message)" -Sev 'Error' -LogData $LogData - throw 'Failed to create a new PwPush link, check the log book for more details' + Write-LogMessage -API PwPush -Message "Continuing without PwPush link due to error" -Sev 'Warning' + return $false } - } else { + } catch { + Write-LogMessage -API PwPush -Message "Unexpected error in PwPush configuration handling: $($_.Exception.Message)" -Sev 'Error' return $false } } diff --git a/Tools/cipp-openapispec.json b/Tools/cipp-openapispec.json new file mode 100644 index 000000000000..0efd9e314077 --- /dev/null +++ b/Tools/cipp-openapispec.json @@ -0,0 +1,1756 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "CIPP API", + "description": "API for Cloud Identity and Policy Platform (CIPP)", + "version": "1.0.0" + }, + "servers": [ + { + "url": "/api", + "description": "CIPP API Server" + } + ], + "components": { + "schemas": { + "StandardResponse": { + "type": "object", + "properties": { + "Results": { + "type": "object", + "description": "The results of the operation" + } + } + } + } + }, + "paths": { + "/ListScheduledItems": { + "get": { + "summary": "List Scheduled Items", + "description": "Retrieves a list of scheduled items", + "tags": [ + "Scheduler" + ], + "parameters": [ + { + "name": "ShowHidden", + "in": "query", + "description": "Whether to show hidden system jobs", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "Name", + "in": "query", + "description": "Filter by job name", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Scheduled items retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "ExecutedTime": { + "type": "string", + "description": "When the job was last executed" + }, + "TaskState": { + "type": "string", + "description": "Current state of the task", + "enum": ["Running", "Planned", "Failed", "Completed"] + }, + "Tenant": { + "type": "string", + "description": "The tenant the job is for" + }, + "Name": { + "type": "string", + "description": "Name of the scheduled job" + }, + "ScheduledTime": { + "type": "integer", + "description": "When the job is scheduled to run (Unix timestamp)" + }, + "Command": { + "type": "string", + "description": "The command to execute" + }, + "Parameters": { + "type": "object", + "description": "Parameters for the command" + }, + "PostExecution": { + "type": "string", + "description": "Actions to take after execution" + }, + "Recurrence": { + "type": "string", + "description": "How often the job recurs" + }, + "Results": { + "type": "string", + "description": "Results of the job execution" + }, + "RowKey": { + "type": "string", + "description": "Unique identifier for the job" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/RemoveScheduledItem": { + "post": { + "summary": "Remove Scheduled Item", + "description": "Removes a scheduled item", + "tags": [ + "Scheduler" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string", + "description": "The RowKey of the scheduled item to remove" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Scheduled item removed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/AddScheduledItem": { + "post": { + "summary": "Add Scheduled Item", + "description": "Adds a new scheduled item", + "tags": [ + "Scheduler" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "tenantFilter", + "Name", + "command", + "ScheduledTime", + "Recurrence" + ], + "properties": { + "tenantFilter": { + "type": "object", + "description": "The tenant to run the job for", + "properties": { + "value": { + "type": "string", + "description": "Tenant ID or domain" + }, + "label": { + "type": "string", + "description": "Tenant display name" + } + } + }, + "Name": { + "type": "string", + "description": "Name of the scheduled job" + }, + "command": { + "type": "object", + "description": "The command to execute", + "properties": { + "label": { + "type": "string", + "description": "Command display name" + }, + "value": { + "type": "string", + "description": "Command value" + } + } + }, + "ScheduledTime": { + "type": "integer", + "description": "When the job is scheduled to run (Unix timestamp)" + }, + "Recurrence": { + "type": "string", + "description": "How often the job recurs", + "enum": ["0", "1d", "7d", "30d", "365d"] + }, + "parameters": { + "type": "object", + "description": "Parameters for the command" + }, + "RawJsonParameters": { + "type": "string", + "description": "JSON string of parameters for advanced configuration" + }, + "postExecution": { + "type": "array", + "description": "Actions to take after execution", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "value": { + "type": "string", + "enum": ["Webhook", "Email", "PSA"] + } + } + } + }, + "RowKey": { + "type": "string", + "description": "Unique identifier for the job (for editing existing jobs)" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Scheduled item added successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListFunctionParameters": { + "get": { + "summary": "List Function Parameters", + "description": "Retrieves a list of available functions and their parameters", + "tags": [ + "Scheduler" + ], + "parameters": [ + { + "name": "Module", + "in": "query", + "description": "The module to list functions for", + "required": true, + "schema": { + "type": "string", + "enum": ["CIPPCore"] + } + } + ], + "responses": { + "200": { + "description": "Function parameters retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Function": { + "type": "string", + "description": "Function name" + }, + "Synopsis": { + "type": "string", + "description": "Function description" + }, + "Parameters": { + "type": "array", + "description": "Function parameters", + "items": { + "type": "object", + "properties": { + "Name": { + "type": "string", + "description": "Parameter name" + }, + "Type": { + "type": "string", + "description": "Parameter type" + }, + "Required": { + "type": "boolean", + "description": "Whether the parameter is required" + } + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListTenants": { + "get": { + "summary": "List Tenants", + "description": "Retrieves a list of tenants", + "tags": [ + "Tenants" + ], + "parameters": [ + { + "name": "AllTenantSelector", + "in": "query", + "description": "Whether to include the 'All Tenants' option", + "required": false, + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "Tenants retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "customerId": { + "type": "string", + "description": "Tenant ID" + }, + "defaultDomainName": { + "type": "string", + "description": "Default domain name" + }, + "displayName": { + "type": "string", + "description": "Display name" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + }, + "post": { + "summary": "Clear Tenant Cache", + "description": "Clears the tenant cache", + "tags": [ + "Tenants" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ClearCache" + ], + "properties": { + "ClearCache": { + "type": "boolean", + "description": "Whether to clear the cache" + }, + "TenantsOnly": { + "type": "boolean", + "description": "Whether to only clear the tenant cache" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Cache cleared successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecPasswordConfig": { + "get": { + "summary": "Get Password Configuration", + "description": "Retrieves the current password configuration", + "tags": [ + "Settings" + ], + "parameters": [ + { + "name": "list", + "in": "query", + "description": "Whether to list the password configuration", + "required": true, + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "Password configuration retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Results": { + "type": "object", + "properties": { + "passwordType": { + "type": "string", + "description": "The type of password generation", + "enum": ["Classic", "Correct-Battery-Horse"] + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + }, + "post": { + "summary": "Update Password Configuration", + "description": "Updates the password configuration", + "tags": [ + "Settings" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "passwordType" + ], + "properties": { + "passwordType": { + "type": "string", + "description": "The type of password generation", + "enum": ["Classic", "Correct-Battery-Horse"] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Password configuration updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecListBackup": { + "get": { + "summary": "List Backups", + "description": "Retrieves a list of backups", + "tags": [ + "Backup" + ], + "parameters": [ + { + "name": "NameOnly", + "in": "query", + "description": "Whether to only return backup names", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "BackupName", + "in": "query", + "description": "The name of a specific backup to retrieve", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Backups retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "BackupName": { + "type": "string", + "description": "Name of the backup" + }, + "Timestamp": { + "type": "string", + "description": "When the backup was created" + }, + "Backup": { + "type": "string", + "description": "The backup data (JSON string)" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecRunBackup": { + "post": { + "summary": "Run Backup", + "description": "Creates a new backup", + "tags": [ + "Backup" + ], + "responses": { + "200": { + "description": "Backup created successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecSetCIPPAutoBackup": { + "post": { + "summary": "Set Automatic Backup", + "description": "Enables or disables automatic backups", + "tags": [ + "Backup" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "Enabled" + ], + "properties": { + "Enabled": { + "type": "boolean", + "description": "Whether to enable automatic backups" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Automatic backup setting updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecRestoreBackup": { + "post": { + "summary": "Restore Backup", + "description": "Restores a backup", + "tags": [ + "Backup" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "type": "object", + "required": [ + "BackupName" + ], + "properties": { + "BackupName": { + "type": "string", + "description": "The name of the backup to restore" + } + } + }, + { + "type": "object", + "description": "The backup data to restore" + } + ] + } + } + } + }, + "responses": { + "200": { + "description": "Backup restored successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/Listlogs": { + "get": { + "summary": "List Logs", + "description": "Retrieves a list of logs", + "tags": [ + "Logs" + ], + "parameters": [ + { + "name": "DateFilter", + "in": "query", + "description": "Filter logs by date (YYYYMMDD format)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Filter", + "in": "query", + "description": "Whether to apply filtering", + "required": false, + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "Logs retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "DateTime": { + "type": "string", + "description": "When the log entry was created" + }, + "Tenant": { + "type": "string", + "description": "The tenant the log entry is for" + }, + "TenantID": { + "type": "string", + "description": "The tenant ID" + }, + "User": { + "type": "string", + "description": "The user who performed the action" + }, + "Message": { + "type": "string", + "description": "The log message" + }, + "API": { + "type": "string", + "description": "The API that was called" + }, + "Severity": { + "type": "string", + "description": "The severity of the log entry" + }, + "AppId": { + "type": "string", + "description": "The application ID" + }, + "IP": { + "type": "string", + "description": "The IP address of the user" + }, + "LogData": { + "type": "string", + "description": "Additional log data" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListExtensionsConfig": { + "get": { + "summary": "List Extensions Configuration", + "description": "Retrieves the configuration for extensions", + "tags": [ + "Integrations" + ], + "responses": { + "200": { + "description": "Extensions configuration retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "Enabled": { + "type": "boolean", + "description": "Whether the extension is enabled" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecExtensionsConfig": { + "post": { + "summary": "Update Extensions Configuration", + "description": "Updates the configuration for extensions", + "tags": [ + "Integrations" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "Enabled": { + "type": "boolean", + "description": "Whether the extension is enabled" + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Extensions configuration updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecExtensionTest": { + "get": { + "summary": "Test Extension", + "description": "Tests an extension", + "tags": [ + "Integrations" + ], + "parameters": [ + { + "name": "extensionName", + "in": "query", + "description": "The name of the extension to test", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Extension test completed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecExtensionSync": { + "get": { + "summary": "Sync Extension", + "description": "Syncs an extension", + "tags": [ + "Integrations" + ], + "parameters": [ + { + "name": "Extension", + "in": "query", + "description": "The name of the extension to sync", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Extension sync completed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecExtensionMapping": { + "get": { + "summary": "Get Extension Mapping", + "description": "Retrieves the mapping for an extension", + "tags": [ + "Integrations" + ], + "parameters": [ + { + "name": "List", + "in": "query", + "description": "The name of the extension to get mapping for", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Extension mapping retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Mappings": { + "type": "array", + "description": "The mappings for the extension", + "items": { + "type": "object", + "properties": { + "TenantId": { + "type": "string", + "description": "The tenant ID" + }, + "Tenant": { + "type": "string", + "description": "The tenant name" + }, + "IntegrationName": { + "type": "string", + "description": "The integration name" + }, + "IntegrationId": { + "type": "string", + "description": "The integration ID" + }, + "TenantDomain": { + "type": "string", + "description": "The tenant domain" + } + } + } + }, + "Companies": { + "type": "array", + "description": "The companies for the extension", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The company name" + }, + "value": { + "type": "string", + "description": "The company ID" + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + }, + "post": { + "summary": "Update Extension Mapping", + "description": "Updates the mapping for an extension", + "tags": [ + "Integrations" + ], + "parameters": [ + { + "name": "AddMapping", + "in": "query", + "description": "The name of the extension to update mapping for", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "AutoMapping", + "in": "query", + "description": "The name of the extension to auto-map", + "required": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "TenantId": { + "type": "string", + "description": "The tenant ID" + }, + "Tenant": { + "type": "string", + "description": "The tenant name" + }, + "IntegrationName": { + "type": "string", + "description": "The integration name" + }, + "IntegrationId": { + "type": "string", + "description": "The integration ID" + }, + "TenantDomain": { + "type": "string", + "description": "The tenant domain" + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Extension mapping updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListExtensionSync": { + "get": { + "summary": "List Extension Sync Jobs", + "description": "Retrieves a list of extension sync jobs", + "tags": [ + "Integrations" + ], + "responses": { + "200": { + "description": "Extension sync jobs retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Tenant": { + "type": "string", + "description": "The tenant the job is for" + }, + "SyncType": { + "type": "string", + "description": "The type of sync" + }, + "Task": { + "type": "string", + "description": "The task being performed" + }, + "ScheduledTime": { + "type": "string", + "description": "When the job is scheduled to run" + }, + "ExecutedTime": { + "type": "string", + "description": "When the job was last executed" + }, + "LastRun": { + "type": "string", + "description": "When the job was last run" + }, + "RepeatsEvery": { + "type": "string", + "description": "How often the job repeats" + }, + "Results": { + "type": "string", + "description": "Results of the job execution" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListExoRequest": { + "post": { + "summary": "List Exchange Cmdlets", + "description": "Retrieves a list of Exchange cmdlets", + "tags": [ + "Exchange" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "type": "object", + "required": [ + "availableCmdlets", + "tenantFilter" + ], + "properties": { + "availableCmdlets": { + "type": "boolean", + "description": "Whether to list available cmdlets" + }, + "tenantFilter": { + "type": "string", + "description": "The tenant to list cmdlets for" + }, + "compliance": { + "type": "boolean", + "description": "Whether to use compliance endpoints" + }, + "asApp": { + "type": "boolean", + "description": "Whether to execute as app" + } + } + }, + { + "type": "object", + "required": [ + "cmdlet", + "cmdParams", + "tenantFilter" + ], + "properties": { + "cmdlet": { + "type": "string", + "description": "The cmdlet to execute" + }, + "cmdParams": { + "type": "object", + "description": "The parameters for the cmdlet" + }, + "compliance": { + "type": "boolean", + "description": "Whether to use compliance endpoints" + }, + "tenantFilter": { + "type": "string", + "description": "The tenant to execute the cmdlet for" + } + } + } + ] + } + } + } + }, + "responses": { + "200": { + "description": "Exchange cmdlets retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Cmdlet": { + "type": "string", + "description": "The cmdlet name" + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecAzBobbyTables": { + "post": { + "summary": "Execute Azure Table Operations", + "description": "Executes operations on Azure tables", + "tags": [ + "Azure Tables" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "FunctionName" + ], + "properties": { + "FunctionName": { + "type": "string", + "description": "The function to execute", + "enum": [ + "Get-AzDataTable", + "Get-AzDataTableEntity", + "Remove-AzDataTableEntity", + "New-AzDataTable", + "Remove-AzDataTable", + "Add-AzDataTableEntity" + ] + }, + "TableName": { + "type": "string", + "description": "The name of the table" + }, + "Parameters": { + "type": "object", + "description": "The parameters for the function" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Azure table operation executed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecCippFunction": { + "post": { + "summary": "Execute CIPP Function", + "description": "Executes a CIPP function", + "tags": [ + "CIPP Functions" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "FunctionName" + ], + "properties": { + "FunctionName": { + "type": "string", + "description": "The function to execute", + "enum": [ + "Get-CIPPTimerFunctions", + "!Get-CIPPTimerFunctions" + ] + }, + "Parameters": { + "type": "object", + "description": "The parameters for the function" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "CIPP function executed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecApiClient": { + "get": { + "summary": "Get API Client Information", + "description": "Retrieves information about API clients", + "tags": [ + "API Clients" + ], + "parameters": [ + { + "name": "Action", + "in": "query", + "description": "The action to perform", + "required": true, + "schema": { + "type": "string", + "enum": [ + "GetAzureConfiguration", + "List", + "ListAvailable" + ] + } + } + ], + "responses": { + "200": { + "description": "API client information retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Results": { + "oneOf": [ + { + "type": "object", + "properties": { + "Enabled": { + "type": "boolean", + "description": "Whether Microsoft Authentication is enabled" + }, + "ApiUrl": { + "type": "string", + "description": "The API URL" + }, + "TenantID": { + "type": "string", + "description": "The tenant ID" + }, + "ClientIDs": { + "type": "array", + "description": "The client IDs", + "items": { + "type": "string" + } + } + } + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "Enabled": { + "type": "boolean", + "description": "Whether the client is enabled" + }, + "AppName": { + "type": "string", + "description": "The application name" + }, + "ClientId": { + "type": "string", + "description": "The client ID" + }, + "Role": { + "type": "string", + "description": "The client role" + }, + "IPRange": { + "type": "array", + "description": "The allowed IP ranges", + "items": { + "type": "string" + } + } + } + } + } + ] + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + }, + "post": { + "summary": "Update API Client", + "description": "Updates an API client", + "tags": [ + "API Clients" + ], + "parameters": [ + { + "name": "action", + "in": "query", + "description": "The action to perform", + "required": false, + "schema": { + "type": "string", + "enum": [ + "SaveToAzure" + ] + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "Action" + ], + "properties": { + "Action": { + "type": "string", + "description": "The action to perform", + "enum": [ + "AddUpdate", + "ResetSecret", + "Delete" + ] + }, + "ClientId": { + "type": "string", + "description": "The client ID" + }, + "AppName": { + "type": "string", + "description": "The application name" + }, + "Role": { + "type": "string", + "description": "The client role" + }, + "IPRange": { + "type": "array", + "description": "The allowed IP ranges", + "items": { + "type": "string" + } + }, + "Enabled": { + "type": "boolean", + "description": "Whether the client is enabled" + }, + "RemoveAppReg": { + "type": "boolean", + "description": "Whether to remove the app registration" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "API client updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListCustomRole": { + "get": { + "summary": "List Custom Roles", + "description": "Retrieves a list of custom roles", + "tags": [ + "API Clients" + ], + "responses": { + "200": { + "description": "Custom roles retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "RowKey": { + "type": "string", + "description": "The role name" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + } + } +} \ No newline at end of file diff --git a/Tools/endpoint-openapispec.json b/Tools/endpoint-openapispec.json new file mode 100644 index 000000000000..7fb45816d2ce --- /dev/null +++ b/Tools/endpoint-openapispec.json @@ -0,0 +1,2263 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "CIPP Endpoint API", + "description": "API endpoints for the Endpoint section of Cloud Identity and Policy Platform (CIPP)", + "version": "1.0.0" + }, + "servers": [ + { + "url": "/api", + "description": "CIPP API Server" + } + ], + "components": { + "schemas": { + "StandardResponse": { + "type": "object", + "properties": { + "Results": { + "type": "object", + "description": "The results of the operation" + } + } + } + } + }, + "paths": { + "/ListApps": { + "get": { + "summary": "List Applications", + "description": "Retrieves a list of applications", + "tags": [ + "Applications" + ], + "parameters": [ + { + "name": "tenantFilter", + "in": "query", + "description": "The tenant to filter by", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Applications retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The application ID" + }, + "displayName": { + "type": "string", + "description": "The display name of the application" + }, + "publishingState": { + "type": "string", + "description": "The publishing state of the application" + }, + "installCommandLine": { + "type": "string", + "description": "The install command line" + }, + "uninstallCommandLine": { + "type": "string", + "description": "The uninstall command line" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecAssignApp": { + "post": { + "summary": "Assign Application", + "description": "Assigns an application to users or devices", + "tags": [ + "Applications" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "AssignTo", + "ID" + ], + "properties": { + "AssignTo": { + "type": "string", + "description": "Who to assign the application to", + "enum": ["AllUsers", "AllDevices", "Both", "customGroup"] + }, + "ID": { + "type": "string", + "description": "The application ID" + }, + "customGroup": { + "type": "string", + "description": "Custom group names (if AssignTo is customGroup)" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Application assigned successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/RemoveApp": { + "post": { + "summary": "Remove Application", + "description": "Removes an application", + "tags": [ + "Applications" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ID" + ], + "properties": { + "ID": { + "type": "string", + "description": "The application ID" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Application removed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListApplicationQueue": { + "get": { + "summary": "List Application Queue", + "description": "Retrieves a list of applications in the queue", + "tags": [ + "Applications" + ], + "parameters": [ + { + "name": "tenantFilter", + "in": "query", + "description": "The tenant to filter by", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Application queue retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The queue item ID" + }, + "applicationName": { + "type": "string", + "description": "The application name" + }, + "status": { + "type": "string", + "description": "The status of the queue item" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/RemoveQueuedApp": { + "post": { + "summary": "Remove Queued Application", + "description": "Removes an application from the queue", + "tags": [ + "Applications" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ID" + ], + "properties": { + "ID": { + "type": "string", + "description": "The queue item ID" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Queued application removed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecAppUpload": { + "post": { + "summary": "Execute Application Upload", + "description": "Executes the application upload process", + "tags": [ + "Applications" + ], + "responses": { + "200": { + "description": "Application upload executed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/AddMSPApp": { + "post": { + "summary": "Add MSP Application", + "description": "Adds an MSP vendor application", + "tags": [ + "Applications" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "selectedTenants", + "rmmname", + "displayName" + ], + "properties": { + "selectedTenants": { + "type": "array", + "description": "The tenants to add the application to", + "items": { + "type": "object", + "properties": { + "defaultDomainName": { + "type": "string", + "description": "The tenant domain name" + }, + "customerId": { + "type": "string", + "description": "The tenant ID" + } + } + } + }, + "rmmname": { + "type": "object", + "description": "The RMM tool", + "properties": { + "value": { + "type": "string", + "enum": ["datto", "syncro", "immy", "huntress", "automate", "cwcommand"] + } + } + }, + "displayName": { + "type": "string", + "description": "The display name of the application" + }, + "params": { + "type": "object", + "description": "Parameters specific to the RMM tool" + }, + "AssignTo": { + "type": "string", + "description": "Who to assign the application to", + "enum": ["On", "allLicensedUsers", "AllDevices", "AllDevicesAndUsers", "customGroup"] + }, + "customGroup": { + "type": "string", + "description": "Custom group names (if AssignTo is customGroup)" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "MSP application added successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/AddStoreApp": { + "post": { + "summary": "Add Store Application", + "description": "Adds a store application", + "tags": [ + "Applications" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "selectedTenants", + "packagename", + "applicationName" + ], + "properties": { + "selectedTenants": { + "type": "array", + "description": "The tenants to add the application to", + "items": { + "type": "object", + "properties": { + "defaultDomainName": { + "type": "string", + "description": "The tenant domain name" + }, + "customerId": { + "type": "string", + "description": "The tenant ID" + } + } + } + }, + "packagename": { + "type": "string", + "description": "The package identifier" + }, + "applicationName": { + "type": "string", + "description": "The application name" + }, + "description": { + "type": "string", + "description": "The application description" + }, + "InstallationIntent": { + "type": "boolean", + "description": "Whether to mark for uninstallation" + }, + "AssignTo": { + "type": "string", + "description": "Who to assign the application to", + "enum": ["On", "allLicensedUsers", "AllDevices", "AllDevicesAndUsers", "customGroup"] + }, + "customGroup": { + "type": "string", + "description": "Custom group names (if AssignTo is customGroup)" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Store application added successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/AddwinGetApp": { + "post": { + "summary": "Add WinGet Application", + "description": "Adds a WinGet application", + "tags": [ + "Applications" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "selectedTenants", + "packagename", + "applicationName" + ], + "properties": { + "selectedTenants": { + "type": "array", + "description": "The tenants to add the application to", + "items": { + "type": "object", + "properties": { + "defaultDomainName": { + "type": "string", + "description": "The tenant domain name" + }, + "customerId": { + "type": "string", + "description": "The tenant ID" + } + } + } + }, + "packagename": { + "type": "string", + "description": "The package identifier" + }, + "applicationName": { + "type": "string", + "description": "The application name" + }, + "description": { + "type": "string", + "description": "The application description" + }, + "InstallationIntent": { + "type": "boolean", + "description": "Whether to mark for uninstallation" + }, + "AssignTo": { + "type": "string", + "description": "Who to assign the application to", + "enum": ["On", "allLicensedUsers", "AllDevices", "AllDevicesAndUsers", "customGroup"] + }, + "customGroup": { + "type": "string", + "description": "Custom group names (if AssignTo is customGroup)" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "WinGet application added successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/AddChocoApp": { + "post": { + "summary": "Add Chocolatey Application", + "description": "Adds a Chocolatey application", + "tags": [ + "Applications" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "selectedTenants", + "packagename", + "applicationName" + ], + "properties": { + "selectedTenants": { + "type": "array", + "description": "The tenants to add the application to", + "items": { + "type": "object", + "properties": { + "defaultDomainName": { + "type": "string", + "description": "The tenant domain name" + }, + "customerId": { + "type": "string", + "description": "The tenant ID" + } + } + } + }, + "packagename": { + "type": "string", + "description": "The package name" + }, + "applicationName": { + "type": "string", + "description": "The application name" + }, + "description": { + "type": "string", + "description": "The application description" + }, + "customRepo": { + "type": "string", + "description": "Custom repository URL" + }, + "InstallAsSystem": { + "type": "boolean", + "description": "Whether to install as system" + }, + "DisableRestart": { + "type": "boolean", + "description": "Whether to disable restart" + }, + "InstallationIntent": { + "type": "boolean", + "description": "Whether to mark for uninstallation" + }, + "AssignTo": { + "type": "string", + "description": "Who to assign the application to", + "enum": ["On", "allLicensedUsers", "AllDevices", "AllDevicesAndUsers", "customGroup"] + }, + "customGroup": { + "type": "string", + "description": "Custom group names (if AssignTo is customGroup)" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Chocolatey application added successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/AddOfficeApp": { + "post": { + "summary": "Add Office Application", + "description": "Adds a Microsoft Office application", + "tags": [ + "Applications" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "selectedTenants", + "updateChannel", + "languages" + ], + "properties": { + "selectedTenants": { + "type": "array", + "description": "The tenants to add the application to", + "items": { + "type": "object", + "properties": { + "defaultDomainName": { + "type": "string", + "description": "The tenant domain name" + }, + "customerId": { + "type": "string", + "description": "The tenant ID" + } + } + } + }, + "excludedApps": { + "type": "array", + "description": "Apps to exclude from the installation", + "items": { + "type": "object", + "properties": { + "value": { + "type": "string", + "enum": ["access", "excel", "oneNote", "outlook", "powerPoint", "teams", "word", "lync", "bing"] + } + } + } + }, + "updateChannel": { + "type": "object", + "description": "The update channel", + "properties": { + "value": { + "type": "string", + "enum": ["current", "firstReleaseCurrent", "monthlyEnterprise", "deferred", "firstReleaseDeferred"] + } + } + }, + "languages": { + "type": "array", + "description": "Languages to install", + "items": { + "type": "object", + "properties": { + "value": { + "type": "string", + "description": "Language tag" + } + } + } + }, + "SharedComputerActivation": { + "type": "boolean", + "description": "Whether to use shared computer activation" + }, + "arch": { + "type": "boolean", + "description": "Whether to use 64-bit" + }, + "RemoveVersions": { + "type": "boolean", + "description": "Whether to remove other versions" + }, + "AcceptLicense": { + "type": "boolean", + "description": "Whether to accept the license" + }, + "AssignTo": { + "type": "string", + "description": "Who to assign the application to", + "enum": ["On", "allLicensedUsers", "AllDevices", "AllDevicesAndUsers"] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Office application added successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListAPDevices": { + "get": { + "summary": "List Autopilot Devices", + "description": "Retrieves a list of Autopilot devices", + "tags": [ + "Autopilot" + ], + "parameters": [ + { + "name": "tenantFilter", + "in": "query", + "description": "The tenant to filter by", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Autopilot devices retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The device ID" + }, + "displayName": { + "type": "string", + "description": "The display name of the device" + }, + "serialNumber": { + "type": "string", + "description": "The serial number of the device" + }, + "model": { + "type": "string", + "description": "The model of the device" + }, + "manufacturer": { + "type": "string", + "description": "The manufacturer of the device" + }, + "groupTag": { + "type": "string", + "description": "The group tag of the device" + }, + "enrollmentState": { + "type": "string", + "description": "The enrollment state of the device" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecAssignAPDevice": { + "post": { + "summary": "Assign Autopilot Device", + "description": "Assigns an Autopilot device to a user", + "tags": [ + "Autopilot" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "device", + "serialNumber", + "user" + ], + "properties": { + "device": { + "type": "string", + "description": "The device ID" + }, + "serialNumber": { + "type": "string", + "description": "The serial number of the device" + }, + "user": { + "type": "string", + "description": "The user principal name" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Autopilot device assigned successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/RemoveAPDevice": { + "post": { + "summary": "Remove Autopilot Device", + "description": "Removes an Autopilot device", + "tags": [ + "Autopilot" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ID" + ], + "properties": { + "ID": { + "type": "string", + "description": "The device ID" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Autopilot device removed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecSyncAPDevices": { + "post": { + "summary": "Sync Autopilot Devices", + "description": "Syncs Autopilot devices", + "tags": [ + "Autopilot" + ], + "responses": { + "200": { + "description": "Autopilot devices synced successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListAutopilotConfig": { + "get": { + "summary": "List Autopilot Configurations", + "description": "Retrieves a list of Autopilot configurations", + "tags": [ + "Autopilot" + ], + "parameters": [ + { + "name": "type", + "in": "query", + "description": "The type of configuration to retrieve", + "required": false, + "schema": { + "type": "string", + "enum": ["ESP", "ApProfile"] + } + }, + { + "name": "tenantFilter", + "in": "query", + "description": "The tenant to filter by", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Autopilot configurations retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The configuration ID" + }, + "displayName": { + "type": "string", + "description": "The display name of the configuration" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListDevices": { + "get": { + "summary": "List Devices", + "description": "Retrieves a list of devices", + "tags": [ + "Devices" + ], + "parameters": [ + { + "name": "tenantFilter", + "in": "query", + "description": "The tenant to filter by", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Devices retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The device ID" + }, + "displayName": { + "type": "string", + "description": "The display name of the device" + }, + "manufacturer": { + "type": "string", + "description": "The manufacturer of the device" + }, + "model": { + "type": "string", + "description": "The model of the device" + }, + "osVersion": { + "type": "string", + "description": "The OS version of the device" + }, + "lastSyncDateTime": { + "type": "string", + "description": "The last sync date and time" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecDeviceAction": { + "post": { + "summary": "Execute Device Action", + "description": "Executes an action on a device", + "tags": [ + "Devices" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "Action", + "DeviceID" + ], + "properties": { + "Action": { + "type": "string", + "description": "The action to perform", + "enum": ["Reboot", "Rename", "Autopilot", "Wipe", "RemoveFromAutopilot", "RemoveFromIntune", "RemoveFromDefender", "RemoveFromAzure", "RemoveFromEverywhere", "SyncDevice", "FreshStart", "QuickScan", "FullScan", "WindowsUpdateScan", "WindowsUpdateReboot", "WindowsUpdateDrivers", "WindowsUpdateFeatures", "WindowsUpdateOther", "WindowsUpdateAll"] + }, + "DeviceID": { + "type": "string", + "description": "The device ID" + }, + "NewDeviceName": { + "type": "string", + "description": "The new device name (for Rename action)" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Device action executed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecGetLocalAdminPassword": { + "post": { + "summary": "Get Local Admin Password", + "description": "Retrieves the local admin password for a device", + "tags": [ + "Devices" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "DeviceID" + ], + "properties": { + "DeviceID": { + "type": "string", + "description": "The device ID" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Local admin password retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecGetRecoveryKey": { + "post": { + "summary": "Get Recovery Key", + "description": "Retrieves the recovery key for a device", + "tags": [ + "Devices" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "DeviceID" + ], + "properties": { + "DeviceID": { + "type": "string", + "description": "The device ID" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Recovery key retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListIntunePolicy": { + "get": { + "summary": "List Intune Policies", + "description": "Retrieves a list of Intune policies", + "tags": [ + "Intune" + ], + "parameters": [ + { + "name": "type", + "in": "query", + "description": "The type of policy to retrieve", + "required": false, + "schema": { + "type": "string", + "enum": ["ESP"] + } + }, + { + "name": "tenantFilter", + "in": "query", + "description": "The tenant to filter by", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Intune policies retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The policy ID" + }, + "displayName": { + "type": "string", + "description": "The display name of the policy" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/AddPolicy": { + "post": { + "summary": "Add Policy", + "description": "Adds a policy", + "tags": [ + "Intune" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "selectedTenants": { + "type": "array", + "description": "The tenants to add the policy to", + "items": { + "type": "object", + "properties": { + "customerId": { + "type": "string", + "description": "The tenant ID" + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Policy added successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/AddIntuneTemplate": { + "post": { + "summary": "Add Intune Template", + "description": "Adds an Intune template", + "tags": [ + "Intune" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Type": { + "type": "string", + "description": "The type of template" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Intune template added successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecAssignPolicy": { + "post": { + "summary": "Assign Policy", + "description": "Assigns a policy", + "tags": [ + "Intune" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "AssignTo", + "ID" + ], + "properties": { + "AssignTo": { + "type": "string", + "description": "Who to assign the policy to", + "enum": ["AllUsers", "AllDevices", "Both"] + }, + "ID": { + "type": "string", + "description": "The policy ID" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Policy assigned successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/RemovePolicy": { + "post": { + "summary": "Remove Policy", + "description": "Removes a policy", + "tags": [ + "Intune" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ID" + ], + "properties": { + "ID": { + "type": "string", + "description": "The policy ID" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Policy removed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListIntuneTemplates": { + "get": { + "summary": "List Intune Templates", + "description": "Retrieves a list of Intune templates", + "tags": [ + "Intune" + ], + "parameters": [ + { + "name": "View", + "in": "query", + "description": "Whether to view the templates", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "tenantFilter", + "in": "query", + "description": "The tenant to filter by", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Intune templates retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "GUID": { + "type": "string", + "description": "The template ID" + }, + "displayName": { + "type": "string", + "description": "The display name of the template" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecEditTemplate": { + "post": { + "summary": "Edit Template", + "description": "Edits a template", + "tags": [ + "Intune" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "GUID": { + "type": "string", + "description": "The template ID" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Template edited successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecCommunityRepo": { + "post": { + "summary": "Execute Community Repository", + "description": "Executes a community repository", + "tags": [ + "Intune" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "RepoURL": { + "type": "string", + "description": "The repository URL" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Community repository executed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/RemoveIntuneTemplate": { + "post": { + "summary": "Remove Intune Template", + "description": "Removes an Intune template", + "tags": [ + "Intune" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ID" + ], + "properties": { + "ID": { + "type": "string", + "description": "The template ID" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Intune template removed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListIntuneScript": { + "get": { + "summary": "List Intune Scripts", + "description": "Retrieves a list of Intune scripts", + "tags": [ + "Intune" + ], + "parameters": [ + { + "name": "tenantFilter", + "in": "query", + "description": "The tenant to filter by", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Intune scripts retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The script ID" + }, + "displayName": { + "type": "string", + "description": "The display name of the script" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/RemoveIntuneScript": { + "post": { + "summary": "Remove Intune Script", + "description": "Removes an Intune script", + "tags": [ + "Intune" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ID" + ], + "properties": { + "ID": { + "type": "string", + "description": "The script ID" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Intune script removed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListGraphRequest": { + "get": { + "summary": "List Graph Request", + "description": "Retrieves data from a Graph API request", + "tags": [ + "Graph" + ], + "parameters": [ + { + "name": "tenantFilter", + "in": "query", + "description": "The tenant to filter by", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "endpoint", + "in": "query", + "description": "The Graph API endpoint", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Graph request data retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Results": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/listUsers": { + "get": { + "summary": "List Users", + "description": "Retrieves a list of users", + "tags": [ + "Users" + ], + "parameters": [ + { + "name": "tenantFilter", + "in": "query", + "description": "The tenant to filter by", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Users retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "userPrincipalName": { + "type": "string", + "description": "The user principal name" + }, + "displayName": { + "type": "string", + "description": "The display name of the user" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListAppsRepository": { + "post": { + "summary": "List Apps Repository", + "description": "Searches the apps repository", + "tags": [ + "Applications" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "search" + ], + "properties": { + "search": { + "type": "string", + "description": "The search query" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Apps repository search results retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "packagename": { + "type": "string", + "description": "The package name" + }, + "applicationName": { + "type": "string", + "description": "The application name" + }, + "description": { + "type": "string", + "description": "The application description" + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListPotentialApps": { + "post": { + "summary": "List Potential Apps", + "description": "Searches for potential apps", + "tags": [ + "Applications" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "searchString", + "type" + ], + "properties": { + "searchString": { + "type": "string", + "description": "The search query" + }, + "type": { + "type": "string", + "description": "The type of apps to search for", + "enum": ["WinGet"] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Potential apps search results retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "packagename": { + "type": "string", + "description": "The package name" + }, + "applicationName": { + "type": "string", + "description": "The application name" + }, + "description": { + "type": "string", + "description": "The application description" + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListExtensionsConfig": { + "get": { + "summary": "List Extensions Configuration", + "description": "Retrieves the configuration for extensions", + "tags": [ + "Extensions" + ], + "responses": { + "200": { + "description": "Extensions configuration retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "Enabled": { + "type": "boolean", + "description": "Whether the extension is enabled" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListCommunityRepos": { + "get": { + "summary": "List Community Repositories", + "description": "Retrieves a list of community repositories", + "tags": [ + "Intune" + ], + "parameters": [ + { + "name": "tenantFilter", + "in": "query", + "description": "The tenant to filter by", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Community repositories retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "RepoURL": { + "type": "string", + "description": "The repository URL" + }, + "RepoName": { + "type": "string", + "description": "The repository name" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + } + } +} \ No newline at end of file diff --git a/Tools/identity-openapispec.json b/Tools/identity-openapispec.json new file mode 100644 index 000000000000..72e8871a8913 --- /dev/null +++ b/Tools/identity-openapispec.json @@ -0,0 +1,1774 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "CIPP Identity API", + "description": "API endpoints for identity management in CIPP", + "version": "1.0.0" + }, + "paths": { + "/api/ListGraphRequest": { + "get": { + "summary": "List Graph Request", + "description": "Generic endpoint for making Graph API requests with different parameters", + "parameters": [ + { + "name": "Endpoint", + "in": "query", + "description": "The Graph API endpoint to call", + "required": true, + "schema": { + "type": "string" + }, + "examples": { + "users": { + "value": "users" + }, + "devices": { + "value": "devices" + }, + "identityProtection/riskDetections": { + "value": "identityProtection/riskDetections" + }, + "identityProtection/riskyUsers": { + "value": "identityProtection/riskyUsers" + } + } + }, + { + "name": "manualPagination", + "in": "query", + "description": "Whether to use manual pagination", + "schema": { + "type": "boolean" + } + }, + { + "name": "$select", + "in": "query", + "description": "Fields to select", + "schema": { + "type": "string" + } + }, + { + "name": "$count", + "in": "query", + "description": "Whether to include count", + "schema": { + "type": "boolean" + } + }, + { + "name": "$orderby", + "in": "query", + "description": "Field to order by", + "schema": { + "type": "string" + } + }, + { + "name": "$top", + "in": "query", + "description": "Number of records to return", + "schema": { + "type": "integer" + } + }, + { + "name": "$format", + "in": "query", + "description": "Response format", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Results": { + "type": "array", + "items": { + "type": "object" + } + }, + "Metadata": { + "type": "object" + } + } + } + } + } + } + } + } + }, + "/api/ExecCreateTAP": { + "post": { + "summary": "Create Temporary Access Password", + "description": "Creates a temporary access password for a user", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ID": { + "type": "string", + "description": "User Principal Name" + } + }, + "required": ["ID"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ExecResetMFA": { + "post": { + "summary": "Reset MFA", + "description": "Re-requires MFA registration for a user", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ID": { + "type": "string", + "description": "User Principal Name" + } + }, + "required": ["ID"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ExecSendPush": { + "post": { + "summary": "Send MFA Push", + "description": "Sends an MFA push notification to a user", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "UserEmail": { + "type": "string", + "description": "User Principal Name" + } + }, + "required": ["UserEmail"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ExecPerUserMFA": { + "post": { + "summary": "Set Per-User MFA", + "description": "Sets per-user MFA for a user", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User Principal Name" + }, + "State": { + "type": "string", + "enum": ["Enforced", "Enabled", "Disabled"], + "description": "MFA State" + } + }, + "required": ["userId", "State"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ExecConvertMailbox": { + "post": { + "summary": "Convert Mailbox", + "description": "Converts a mailbox between shared and regular types", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ID": { + "type": "string", + "description": "User Principal Name" + }, + "MailboxType": { + "type": "string", + "enum": ["!Shared", "!Regular"], + "description": "Mailbox Type" + } + }, + "required": ["ID", "MailboxType"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ExecEnableArchive": { + "post": { + "summary": "Enable Online Archive", + "description": "Enables online archive for a user", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ID": { + "type": "string", + "description": "User Principal Name" + } + }, + "required": ["ID"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ExecSetOoO": { + "post": { + "summary": "Set Out of Office", + "description": "Sets or disables out of office for a user", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User Principal Name" + }, + "AutoReplyState": { + "type": "string", + "enum": ["Enabled", "Disabled"], + "description": "Auto Reply State" + }, + "input": { + "type": "string", + "description": "Out of Office Message" + } + }, + "required": ["userId", "AutoReplyState"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/EditGroup": { + "post": { + "summary": "Edit Group", + "description": "Edits a group, including adding/removing members and owners", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "description": "Tenant ID" + }, + "groupId": { + "type": "string", + "description": "Group ID" + }, + "AddMember": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Members to add" + }, + "AddOwner": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Owners to add" + }, + "RemoveMember": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Members to remove" + }, + "RemoveOwner": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Owners to remove" + }, + "addMember": { + "type": "string", + "description": "Single member to add" + }, + "groupId": { + "type": "string", + "description": "Group ID to add member to" + } + }, + "required": ["tenantId", "groupId"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ListGroups": { + "get": { + "summary": "List Groups", + "description": "Lists groups in the tenant", + "parameters": [ + { + "name": "groupID", + "in": "query", + "description": "Group ID to get details for", + "schema": { + "type": "string" + } + }, + { + "name": "tenantFilter", + "in": "query", + "description": "Tenant to filter by", + "schema": { + "type": "string" + } + }, + { + "name": "members", + "in": "query", + "description": "Whether to include members", + "schema": { + "type": "boolean" + } + }, + { + "name": "owners", + "in": "query", + "description": "Whether to include owners", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "groupInfo": { + "type": "object" + }, + "members": { + "type": "array", + "items": { + "type": "object" + } + }, + "owners": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + } + } + } + } + } + }, + "/api/ExecEmailForward": { + "post": { + "summary": "Email Forwarding", + "description": "Manages email forwarding for a user", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "username": { + "type": "string", + "description": "User Principal Name" + }, + "userid": { + "type": "string", + "description": "User Principal Name" + }, + "ForwardOption": { + "type": "string", + "description": "Forward Option" + } + }, + "required": ["username", "userid", "ForwardOption"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ExecOneDriveProvision": { + "post": { + "summary": "Provision OneDrive", + "description": "Pre-provisions OneDrive for a user", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "UserPrincipalName": { + "type": "string", + "description": "User Principal Name" + } + }, + "required": ["UserPrincipalName"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ExecOneDriveShortCut": { + "post": { + "summary": "Add OneDrive Shortcut", + "description": "Adds a shortcut to a SharePoint site in a user's OneDrive", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "username": { + "type": "string", + "description": "User Principal Name" + }, + "userid": { + "type": "string", + "description": "User ID" + }, + "siteUrl": { + "type": "string", + "description": "SharePoint Site URL" + } + }, + "required": ["username", "userid", "siteUrl"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ListSites": { + "get": { + "summary": "List Sites", + "description": "Lists SharePoint sites", + "parameters": [ + { + "name": "type", + "in": "query", + "description": "Type of sites to list", + "schema": { + "type": "string" + } + }, + { + "name": "URLOnly", + "in": "query", + "description": "Whether to return only URLs", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "webUrl": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "/api/ExecDisableUser": { + "post": { + "summary": "Disable/Enable User", + "description": "Blocks or unblocks sign-in for a user", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ID": { + "type": "string", + "description": "User ID" + }, + "Enable": { + "type": "boolean", + "description": "Whether to enable the user" + } + }, + "required": ["ID"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ExecResetPass": { + "post": { + "summary": "Reset Password", + "description": "Resets a user's password", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "MustChange": { + "type": "boolean", + "description": "Whether the user must change password at next logon" + }, + "ID": { + "type": "string", + "description": "User Principal Name" + }, + "displayName": { + "type": "string", + "description": "User Display Name" + } + }, + "required": ["MustChange", "ID"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ExecClrImmId": { + "post": { + "summary": "Clear Immutable ID", + "description": "Clears the immutable ID for a user", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ID": { + "type": "string", + "description": "User ID" + } + }, + "required": ["ID"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ExecRevokeSessions": { + "post": { + "summary": "Revoke Sessions", + "description": "Revokes all sessions for a user", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ID": { + "type": "string", + "description": "User ID" + }, + "Username": { + "type": "string", + "description": "User Principal Name" + } + }, + "required": ["ID", "Username"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/RemoveUser": { + "post": { + "summary": "Remove User", + "description": "Deletes a user", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ID": { + "type": "string", + "description": "User ID" + } + }, + "required": ["ID"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/AddUser": { + "post": { + "summary": "Add User", + "description": "Creates a new user", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "tenantFilter": { + "type": "string", + "description": "Tenant ID" + }, + "givenName": { + "type": "string", + "description": "First Name" + }, + "surname": { + "type": "string", + "description": "Last Name" + }, + "mailNickname": { + "type": "string", + "description": "Mail Nickname" + }, + "primDomain": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "description": "Primary Domain" + }, + "usageLocation": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "description": "Usage Location" + } + }, + "required": ["tenantFilter", "givenName", "surname", "mailNickname", "primDomain"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ListMFAUsers": { + "get": { + "summary": "List MFA Users", + "description": "Lists users with MFA information", + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "UPN": { + "type": "string" + }, + "AccountEnabled": { + "type": "string" + }, + "isLicensed": { + "type": "string" + }, + "MFARegistration": { + "type": "string" + }, + "PerUser": { + "type": "string" + }, + "CoveredBySD": { + "type": "string" + }, + "CoveredByCA": { + "type": "string" + }, + "MFAMethods": { + "type": "array", + "items": { + "type": "string" + } + }, + "CAPolicies": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + }, + "/api/ListSignIns": { + "get": { + "summary": "List Sign Ins", + "description": "Lists sign-in events", + "parameters": [ + { + "name": "Days", + "in": "query", + "description": "Number of days to look back", + "schema": { + "type": "integer" + } + }, + { + "name": "filter", + "in": "query", + "description": "Custom filter", + "schema": { + "type": "string" + } + }, + { + "name": "failedLogonsOnly", + "in": "query", + "description": "Whether to show only failed logons", + "schema": { + "type": "boolean" + } + }, + { + "name": "FailureThreshold", + "in": "query", + "description": "Failure threshold", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "createdDateTime": { + "type": "string" + }, + "userPrincipalName": { + "type": "string" + }, + "clientAppUsed": { + "type": "string" + }, + "authenticationRequirement": { + "type": "string" + }, + "errorCode": { + "type": "string" + }, + "additionalDetails": { + "type": "string" + }, + "ipAddress": { + "type": "string" + }, + "locationcipp": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "/api/ListInactiveAccounts": { + "get": { + "summary": "List Inactive Accounts", + "description": "Lists inactive user accounts (6 months)", + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "tenantDisplayName": { + "type": "string" + }, + "userPrincipalName": { + "type": "string" + }, + "displayName": { + "type": "string" + }, + "lastSignInDateTime": { + "type": "string" + }, + "lastNonInteractiveSignInDateTime": { + "type": "string" + }, + "numberOfAssignedLicenses": { + "type": "integer" + }, + "lastRefreshedDateTime": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "/api/ListAzureADConnectStatus": { + "get": { + "summary": "List Azure AD Connect Status", + "description": "Lists Azure AD Connect status", + "parameters": [ + { + "name": "DataToReturn", + "in": "query", + "description": "Type of data to return", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "displayName": { + "type": "string" + }, + "ObjectType": { + "type": "string" + }, + "createdDateTime": { + "type": "string" + }, + "onPremisesProvisioningErrors": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + } + } + } + } + } + } + }, + "/api/ExecGroupsHideFromGAL": { + "post": { + "summary": "Hide/Unhide Group from GAL", + "description": "Hides or unhides a group from the Global Address List", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ID": { + "type": "string", + "description": "Group Email" + }, + "GroupType": { + "type": "string", + "description": "Group Type" + }, + "HidefromGAL": { + "type": "boolean", + "description": "Whether to hide from GAL" + } + }, + "required": ["ID", "GroupType", "HidefromGAL"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ExecGroupsDeliveryManagement": { + "post": { + "summary": "Manage Group Delivery Settings", + "description": "Manages delivery settings for a group", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ID": { + "type": "string", + "description": "Group Email" + }, + "GroupType": { + "type": "string", + "description": "Group Type" + }, + "OnlyAllowInternal": { + "type": "boolean", + "description": "Whether to only allow internal messages" + } + }, + "required": ["ID", "GroupType", "OnlyAllowInternal"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ExecGroupsDelete": { + "post": { + "summary": "Delete Group", + "description": "Deletes a group", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ID": { + "type": "string", + "description": "Group ID" + }, + "GroupType": { + "type": "string", + "description": "Group Type" + }, + "DisplayName": { + "type": "string", + "description": "Group Display Name" + } + }, + "required": ["ID", "GroupType", "DisplayName"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/AddGroup": { + "post": { + "summary": "Add Group", + "description": "Creates a new group", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "tenantFilter": { + "type": "string", + "description": "Tenant ID" + }, + "groupName": { + "type": "string", + "description": "Group Name" + }, + "groupType": { + "type": "string", + "description": "Group Type" + } + }, + "required": ["tenantFilter", "groupName", "groupType"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ListRoles": { + "get": { + "summary": "List Roles", + "description": "Lists roles in the tenant", + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "DisplayName": { + "type": "string" + }, + "Description": { + "type": "string" + }, + "Members": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + }, + "/api/ExecDismissRiskyUser": { + "post": { + "summary": "Dismiss Risky User", + "description": "Dismisses the risk for a user", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID" + }, + "userDisplayName": { + "type": "string", + "description": "User Display Name" + } + }, + "required": ["userId", "userDisplayName"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ExecJITAdmin": { + "post": { + "summary": "Execute JIT Admin", + "description": "Creates or updates a JIT admin", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "tenantFilter": { + "type": "string", + "description": "Tenant ID" + }, + "userAction": { + "type": "string", + "enum": ["create", "select"], + "description": "User Action" + }, + "firstName": { + "type": "string", + "description": "First Name" + }, + "lastName": { + "type": "string", + "description": "Last Name" + }, + "userName": { + "type": "string", + "description": "Username" + }, + "domain": { + "type": "string", + "description": "Domain Name" + }, + "existingUser": { + "type": "string", + "description": "Existing User" + }, + "startDate": { + "type": "string", + "format": "date", + "description": "Start Date" + }, + "endDate": { + "type": "string", + "format": "date", + "description": "End Date" + }, + "adminRoles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Admin Roles" + }, + "UseTAP": { + "type": "boolean", + "description": "Generate TAP" + }, + "expireAction": { + "type": "string", + "enum": ["DeleteUser", "DisableUser", "RemoveRoles"], + "description": "Expiration Action" + }, + "postExecution": { + "type": "array", + "items": { + "type": "string", + "enum": ["Webhook", "email", "PSA"] + }, + "description": "Notification Action" + } + }, + "required": ["tenantFilter", "userAction", "startDate", "endDate", "adminRoles"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + }, + "get": { + "summary": "List JIT Admins", + "description": "Lists JIT admins", + "parameters": [ + { + "name": "Action", + "in": "query", + "description": "Action to perform", + "schema": { + "type": "string", + "enum": ["List"] + } + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Results": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + } + } + } + } + } + }, + "/api/ExecDeviceDelete": { + "post": { + "summary": "Manage Device", + "description": "Enables, disables, or deletes a device", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ID": { + "type": "string", + "description": "Device ID" + }, + "action": { + "type": "string", + "enum": ["!Enable", "!Disable", "!Delete"], + "description": "Action to perform" + } + }, + "required": ["ID", "action"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ExecGetRecoveryKey": { + "post": { + "summary": "Get Recovery Key", + "description": "Retrieves BitLocker recovery keys for a device", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "GUID": { + "type": "string", + "description": "Device ID" + } + }, + "required": ["GUID"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ListDeletedItems": { + "get": { + "summary": "List Deleted Items", + "description": "Lists deleted items", + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "displayName": { + "type": "string" + }, + "TargetType": { + "type": "string" + }, + "userPrincipalName": { + "type": "string" + }, + "deletedDateTime": { + "type": "string" + }, + "onPremisesSyncEnabled": { + "type": "boolean" + } + } + } + } + } + } + } + } + } + }, + "/api/ExecRestoreDeleted": { + "post": { + "summary": "Restore Deleted Object", + "description": "Restores a deleted object", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ID": { + "type": "string", + "description": "Object ID" + } + }, + "required": ["ID"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ExecOffboardUser": { + "post": { + "summary": "Offboard User", + "description": "Offboards a user", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "tenantFilter": { + "type": "string", + "description": "Tenant ID" + }, + "user": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Users to offboard" + }, + "Scheduled": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + }, + "description": "Scheduled offboarding" + } + }, + "required": ["tenantFilter", "user"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ListExtensionsConfig": { + "get": { + "summary": "List Extensions Configuration", + "description": "Lists extensions configuration", + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "GitHub": { + "type": "object", + "properties": { + "Enabled": { + "type": "boolean" + } + } + } + } + } + } + } + } + } + } + }, + "/api/ExecCommunityRepo": { + "post": { + "summary": "Execute Community Repository Action", + "description": "Executes an action on a community repository", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Action": { + "type": "string", + "enum": ["UploadTemplate"], + "description": "Action to perform" + }, + "GUID": { + "type": "string", + "description": "Template GUID" + }, + "FullName": { + "type": "string", + "description": "Repository Full Name" + }, + "Message": { + "type": "string", + "description": "Commit Message" + } + }, + "required": ["Action", "GUID", "FullName", "Message"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ListCommunityRepos": { + "get": { + "summary": "List Community Repositories", + "description": "Lists community repositories", + "parameters": [ + { + "name": "WriteAccess", + "in": "query", + "description": "Whether to only show repositories with write access", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "FullName": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + }, + "/api/RemoveGroupTemplate": { + "post": { + "summary": "Remove Group Template", + "description": "Removes a group template", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "ID": { + "type": "string", + "description": "Template GUID" + } + }, + "required": ["ID"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + }, + "/api/ListGroupTemplates": { + "get": { + "summary": "List Group Templates", + "description": "Lists group templates", + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Displayname": { + "type": "string" + }, + "Description": { + "type": "string" + }, + "groupType": { + "type": "string" + }, + "GUID": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "/api/AddGroupTemplate": { + "post": { + "summary": "Add Group Template", + "description": "Creates a new group template", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "tenantFilter": { + "type": "string", + "description": "Tenant ID" + }, + "Displayname": { + "type": "string", + "description": "Template Display Name" + }, + "Description": { + "type": "string", + "description": "Template Description" + }, + "groupType": { + "type": "string", + "description": "Group Type" + } + }, + "required": ["Displayname", "Description", "groupType"] + } + } + } + }, + "responses": { + "200": { + "description": "Successful response" + } + } + } + } + } +} \ No newline at end of file diff --git a/Tools/security-openapispec.json b/Tools/security-openapispec.json new file mode 100644 index 000000000000..d7b388cc3a3e --- /dev/null +++ b/Tools/security-openapispec.json @@ -0,0 +1,891 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "CIPP Security API", + "description": "API endpoints for the Security section of Cloud Identity and Policy Platform (CIPP)", + "version": "1.0.0" + }, + "servers": [ + { + "url": "/api", + "description": "CIPP API Server" + } + ], + "components": { + "schemas": { + "StandardResponse": { + "type": "object", + "properties": { + "Results": { + "type": "object", + "description": "The results of the operation" + } + } + } + } + }, + "paths": { + "/ListDefenderState": { + "get": { + "summary": "List Defender State", + "description": "Retrieves the status of Microsoft Defender across devices", + "tags": [ + "Defender" + ], + "parameters": [ + { + "name": "tenantFilter", + "in": "query", + "description": "The tenant to filter by", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Defender state retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "deviceName": { + "type": "string", + "description": "The name of the device" + }, + "windowsProtectionState": { + "type": "object", + "properties": { + "malwareProtectionEnabled": { + "type": "boolean", + "description": "Whether malware protection is enabled" + }, + "realTimeProtectionEnabled": { + "type": "boolean", + "description": "Whether real-time protection is enabled" + }, + "networkInspectionSystemEnabled": { + "type": "boolean", + "description": "Whether network inspection is enabled" + }, + "deviceState": { + "type": "string", + "description": "The state of the device" + }, + "quickScanOverdue": { + "type": "boolean", + "description": "Whether a quick scan is overdue" + }, + "fullScanOverdue": { + "type": "boolean", + "description": "Whether a full scan is overdue" + }, + "signatureUpdateOverdue": { + "type": "boolean", + "description": "Whether a signature update is overdue" + }, + "rebootRequired": { + "type": "boolean", + "description": "Whether a reboot is required" + }, + "lastReportedDateTime": { + "type": "string", + "format": "date-time", + "description": "The date and time of the last report" + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListDefenderTVM": { + "get": { + "summary": "List Defender Threat & Vulnerability Management", + "description": "Retrieves software vulnerabilities detected by Microsoft Defender", + "tags": [ + "Defender" + ], + "parameters": [ + { + "name": "tenantFilter", + "in": "query", + "description": "The tenant to filter by", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Defender TVM data retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "affectedDevicesCount": { + "type": "integer", + "description": "The number of affected devices" + }, + "affectedDevices": { + "type": "array", + "description": "The list of affected devices", + "items": { + "type": "string" + } + }, + "osPlatform": { + "type": "string", + "description": "The OS platform" + }, + "softwareVendor": { + "type": "string", + "description": "The software vendor" + }, + "softwareName": { + "type": "string", + "description": "The software name" + }, + "vulnerabilitySeverityLevel": { + "type": "string", + "description": "The severity level of the vulnerability" + }, + "cvssScore": { + "type": "number", + "description": "The CVSS score" + }, + "securityUpdateAvailable": { + "type": "boolean", + "description": "Whether a security update is available" + }, + "exploitabilityLevel": { + "type": "string", + "description": "The exploitability level" + }, + "cveId": { + "type": "string", + "description": "The CVE ID" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/AddDefenderDeployment": { + "post": { + "summary": "Add Defender Deployment", + "description": "Deploys Microsoft Defender policies to selected tenants", + "tags": [ + "Defender" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "selectedTenants" + ], + "properties": { + "selectedTenants": { + "type": "array", + "description": "The tenants to deploy to", + "items": { + "type": "object", + "properties": { + "value": { + "type": "string", + "description": "Tenant ID" + }, + "label": { + "type": "string", + "description": "Tenant display name" + } + } + } + }, + "Compliance": { + "type": "object", + "description": "Compliance settings", + "properties": { + "AllowMEMEnforceCompliance": { + "type": "boolean", + "description": "Allow Microsoft Defender for Endpoint to enforce Endpoint Security Configurations" + }, + "ConnectIosCompliance": { + "type": "boolean", + "description": "Connect iOS/iPadOS devices version 13.0 and above to Microsoft Defender for Endpoint" + }, + "ConnectAndroidCompliance": { + "type": "boolean", + "description": "Connect Android devices version 6.0.0 and above to Microsoft Defender for Endpoint" + }, + "ConnectWindows": { + "type": "boolean", + "description": "Connect Windows devices version 10.0.15063 and above to Microsoft Defender for Endpoint" + }, + "AppSync": { + "type": "boolean", + "description": "Enable App Sync for iOS/iPadOS devices" + }, + "BlockunsupportedOS": { + "type": "boolean", + "description": "Block unsupported OS versions" + }, + "ConnectAndroid": { + "type": "boolean", + "description": "Connect Android devices to Microsoft Defender for Endpoint" + }, + "ConnectIos": { + "type": "boolean", + "description": "Connect iOS/iPadOS devices to Microsoft Defender for Endpoint" + } + } + }, + "EDR": { + "type": "object", + "description": "EDR settings", + "properties": { + "Telemetry": { + "type": "boolean", + "description": "Expedite Telemetry Reporting Frequency" + }, + "Config": { + "type": "boolean", + "description": "Connect Defender Configuration Package automatically from Connector" + }, + "SampleSharing": { + "type": "boolean", + "description": "Enable Sample Sharing" + } + } + }, + "Policy": { + "type": "object", + "description": "Policy settings", + "properties": { + "ScanArchives": { + "type": "boolean", + "description": "Allow Archive Scanning" + }, + "AllowBehavior": { + "type": "boolean", + "description": "Allow behavior monitoring" + }, + "AllowCloudProtection": { + "type": "boolean", + "description": "Allow Cloud Protection" + }, + "AllowEmailScanning": { + "type": "boolean", + "description": "Allow e-mail scanning" + }, + "AllowFullScanNetwork": { + "type": "boolean", + "description": "Allow Full Scan on Network Drives" + }, + "AllowFullScanRemovable": { + "type": "boolean", + "description": "Allow Full Scan on Removable Drives" + }, + "AllowScriptScan": { + "type": "boolean", + "description": "Allow Script Scanning" + }, + "AllowIPS": { + "type": "boolean", + "description": "Allow Intrusion Prevention System" + }, + "LowCPU": { + "type": "boolean", + "description": "Enable Low CPU priority" + }, + "AllowDownloadable": { + "type": "boolean", + "description": "Allow scanning of downloaded files" + }, + "AllowRealTime": { + "type": "boolean", + "description": "Allow Realtime monitoring" + }, + "AllowNetwork": { + "type": "boolean", + "description": "Allow scanning of mapped drives" + }, + "AllowUI": { + "type": "boolean", + "description": "Allow users to access UI" + }, + "NetworkProtectionBlock": { + "type": "boolean", + "description": "Enable Network Protection in Block Mode" + }, + "NetworkProtectionAudit": { + "type": "boolean", + "description": "Enable Network Protection in Audit Mode" + }, + "CheckSigs": { + "type": "boolean", + "description": "Check Signatures before scan" + }, + "DisableCatchupFullScan": { + "type": "boolean", + "description": "Disable Catchup Full Scan" + }, + "DisableCatchupQuickScan": { + "type": "boolean", + "description": "Disable Catchup Quick Scan" + }, + "AssignTo": { + "type": "string", + "description": "Assignment target", + "enum": ["none", "allLicensedUsers", "AllDevices", "AllDevicesAndUsers"] + } + } + }, + "ASR": { + "type": "object", + "description": "Attack Surface Reduction settings", + "properties": { + "BlockAdobeChild": { + "type": "boolean", + "description": "Block Adobe Reader from creating child processes" + }, + "BlockWin32Macro": { + "type": "boolean", + "description": "Block Win32 API calls from Office macros" + }, + "BlockCredentialStealing": { + "type": "boolean", + "description": "Block credential stealing from the Windows local security authority subsystem" + }, + "BlockPSExec": { + "type": "boolean", + "description": "Block process creations originating from PSExec and WMI commands" + }, + "WMIPersistence": { + "type": "boolean", + "description": "Block persistence through WMI event subscription" + }, + "BlockOfficeExes": { + "type": "boolean", + "description": "Block Office applications from creating executable content" + }, + "BlockOfficeApps": { + "type": "boolean", + "description": "Block Office applications from injecting code into other processes" + }, + "BlockYoungExe": { + "type": "boolean", + "description": "Block executable files from running unless they meet a prevalence, age, or trusted list criterion" + }, + "blockJSVB": { + "type": "boolean", + "description": "Block JavaScript or VBScript from launching downloaded executable content" + }, + "blockOfficeComChild": { + "type": "boolean", + "description": "Block Office communication application from creating child processes" + }, + "blockOfficeChild": { + "type": "boolean", + "description": "Block all Office applications from creating child processes" + }, + "BlockUntrustedUSB": { + "type": "boolean", + "description": "Block untrusted and unsigned processes that run from USB" + }, + "EnableRansomwareVac": { + "type": "boolean", + "description": "Use advanced protection against ransomware" + }, + "BlockExesMail": { + "type": "boolean", + "description": "Block executable content from email client and webmail" + }, + "BlockUnsignedDrivers": { + "type": "boolean", + "description": "Block abuse of exploited vulnerable signed drivers" + }, + "AssignTo": { + "type": "string", + "description": "Assignment target", + "enum": ["none", "allLicensedUsers", "AllDevices", "AllDevicesAndUsers"] + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Defender deployment added successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecAlertsList": { + "get": { + "summary": "List Security Alerts", + "description": "Retrieves a list of security alerts", + "tags": [ + "Incidents" + ], + "parameters": [ + { + "name": "tenantFilter", + "in": "query", + "description": "The tenant to filter by", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Security alerts retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Results": { + "type": "object", + "properties": { + "MSResults": { + "type": "array", + "items": { + "type": "object", + "properties": { + "EventDateTime": { + "type": "string", + "format": "date-time", + "description": "The date and time of the event" + }, + "Status": { + "type": "string", + "description": "The status of the alert" + }, + "Title": { + "type": "string", + "description": "The title of the alert" + }, + "Severity": { + "type": "string", + "description": "The severity of the alert" + }, + "Category": { + "type": "string", + "description": "The category of the alert" + }, + "Tenant": { + "type": "string", + "description": "The tenant name" + }, + "InvolvedUsers": { + "type": "array", + "description": "The users involved in the alert", + "items": { + "type": "string" + } + }, + "Id": { + "type": "string", + "description": "The ID of the alert" + }, + "RawResult": { + "type": "object", + "description": "The raw result data", + "properties": { + "vendorInformation": { + "type": "object", + "properties": { + "vendor": { + "type": "string", + "description": "The vendor name" + }, + "provider": { + "type": "string", + "description": "The provider name" + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecSetSecurityAlert": { + "post": { + "summary": "Set Security Alert Status", + "description": "Updates the status of a security alert", + "tags": [ + "Incidents" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "GUID", + "Status", + "Vendor", + "Provider" + ], + "properties": { + "GUID": { + "type": "string", + "description": "The ID of the alert" + }, + "Status": { + "type": "string", + "description": "The new status of the alert", + "enum": ["!inProgress", "!resolved"] + }, + "Vendor": { + "type": "string", + "description": "The vendor name" + }, + "Provider": { + "type": "string", + "description": "The provider name" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Security alert status updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecIncidentsList": { + "get": { + "summary": "List Security Incidents", + "description": "Retrieves a list of security incidents", + "tags": [ + "Incidents" + ], + "parameters": [ + { + "name": "tenantFilter", + "in": "query", + "description": "The tenant to filter by", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Security incidents retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Created": { + "type": "string", + "format": "date-time", + "description": "The creation date and time" + }, + "Updated": { + "type": "string", + "format": "date-time", + "description": "The last update date and time" + }, + "Tenant": { + "type": "string", + "description": "The tenant name" + }, + "Id": { + "type": "string", + "description": "The ID of the incident" + }, + "RedirectId": { + "type": "string", + "description": "The redirect ID" + }, + "DisplayName": { + "type": "string", + "description": "The display name of the incident" + }, + "Status": { + "type": "string", + "description": "The status of the incident" + }, + "Severity": { + "type": "string", + "description": "The severity of the incident" + }, + "AssignedTo": { + "type": "string", + "description": "The user assigned to the incident" + }, + "Classification": { + "type": "string", + "description": "The classification of the incident" + }, + "Determination": { + "type": "string", + "description": "The determination of the incident" + }, + "IncidentUrl": { + "type": "string", + "description": "The URL to the incident" + }, + "Tags": { + "type": "array", + "description": "The tags associated with the incident", + "items": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecSetSecurityIncident": { + "post": { + "summary": "Set Security Incident Status", + "description": "Updates the status of a security incident or assigns it to a user", + "tags": [ + "Incidents" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "GUID" + ], + "properties": { + "GUID": { + "type": "string", + "description": "The ID of the incident" + }, + "Status": { + "type": "string", + "description": "The new status of the incident", + "enum": ["!active", "!inProgress", "!resolved"] + }, + "Assigned": { + "type": "string", + "description": "The user assigned to the incident" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Security incident updated successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListGraphRequest": { + "get": { + "summary": "List Graph Request", + "description": "Retrieves data from a Graph API request", + "tags": [ + "Graph" + ], + "parameters": [ + { + "name": "tenantFilter", + "in": "query", + "description": "The tenant to filter by", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "endpoint", + "in": "query", + "description": "The Graph API endpoint", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "$top", + "in": "query", + "description": "Number of records to return", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Graph request data retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Results": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + } + } +} \ No newline at end of file diff --git a/Tools/teams-share-openapispec.json b/Tools/teams-share-openapispec.json new file mode 100644 index 000000000000..4c327deadebd --- /dev/null +++ b/Tools/teams-share-openapispec.json @@ -0,0 +1,749 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "CIPP Teams & Share API", + "description": "API endpoints for Teams, SharePoint, and OneDrive management in CIPP", + "version": "1.0.0" + }, + "paths": { + "/api/ListSites": { + "get": { + "summary": "List sites", + "description": "List SharePoint sites or OneDrive accounts based on the type parameter", + "parameters": [ + { + "name": "type", + "in": "query", + "required": true, + "schema": { + "type": "string", + "enum": ["SharePointSiteUsage", "OneDriveUsageAccount"] + }, + "description": "Type of sites to list" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Site" + } + } + } + } + } + } + } + }, + "/api/ExecSetSharePointMember": { + "post": { + "summary": "Add or remove SharePoint site member", + "description": "Add or remove a user as a member of a SharePoint site", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["groupId", "add", "URL", "SharePointType", "user"], + "properties": { + "groupId": { + "type": "string", + "description": "Owner principal name" + }, + "add": { + "type": "boolean", + "description": "True to add, false to remove" + }, + "URL": { + "type": "string", + "description": "Web URL of the site" + }, + "SharePointType": { + "type": "string", + "description": "Root web template" + }, + "user": { + "type": "string", + "description": "User principal name to add or remove" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Operation successful" + } + } + } + }, + "/api/ExecSharePointPerms": { + "post": { + "summary": "Manage SharePoint or OneDrive permissions", + "description": "Add or remove a user as a site admin for SharePoint or add/remove permissions for OneDrive", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["UPN", "RemovePermission", "URL"], + "properties": { + "UPN": { + "type": "string", + "description": "Owner principal name" + }, + "RemovePermission": { + "type": "boolean", + "description": "True to remove permission, false to add" + }, + "URL": { + "type": "string", + "description": "Web URL of the site or OneDrive" + }, + "user": { + "type": "string", + "description": "User principal name to add or remove permissions for" + }, + "onedriveAccessUser": { + "type": "string", + "description": "User principal name to add or remove OneDrive access for" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Operation successful" + } + } + } + }, + "/api/AddSite": { + "post": { + "summary": "Add a new SharePoint site", + "description": "Create a new SharePoint site", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["siteName", "siteDescription", "SiteOwner", "TemplateName", "siteDesign"], + "properties": { + "tenantFilter": { + "type": "string", + "description": "Tenant ID" + }, + "siteName": { + "type": "string", + "description": "Name of the site" + }, + "siteDescription": { + "type": "string", + "description": "Description of the site" + }, + "SiteOwner": { + "type": "string", + "description": "User principal name of the site owner" + }, + "TemplateName": { + "type": "string", + "enum": ["team", "communication"], + "description": "Template name" + }, + "siteDesign": { + "type": "string", + "enum": ["blank", "Showcase", "Topic"], + "description": "Site design template" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Site created successfully" + } + } + } + }, + "/api/AddSiteBulk": { + "post": { + "summary": "Add multiple SharePoint sites", + "description": "Create multiple SharePoint sites in bulk", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["tenantFilter", "bulkSites"], + "properties": { + "tenantFilter": { + "type": "string", + "description": "Tenant ID" + }, + "bulkSites": { + "type": "array", + "items": { + "type": "object", + "properties": { + "SiteName": { + "type": "string", + "description": "Name of the site" + }, + "siteDescription": { + "type": "string", + "description": "Description of the site" + }, + "siteOwner": { + "type": "string", + "description": "User principal name of the site owner" + }, + "TemplateName": { + "type": "string", + "description": "Template name" + }, + "siteDesign": { + "type": "string", + "description": "Site design template" + }, + "sensitivityLabel": { + "type": "string", + "description": "Sensitivity label" + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Sites created successfully" + } + } + } + }, + "/api/ListTeams": { + "get": { + "summary": "List Teams", + "description": "List Microsoft Teams", + "parameters": [ + { + "name": "type", + "in": "query", + "required": true, + "schema": { + "type": "string", + "enum": ["list"] + }, + "description": "Type of Teams list" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Team" + } + } + } + } + } + } + } + }, + "/api/AddTeam": { + "post": { + "summary": "Add a new Team", + "description": "Create a new Microsoft Team", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["tenantID", "displayName", "owner", "visibility"], + "properties": { + "tenantID": { + "type": "string", + "description": "Tenant ID" + }, + "displayName": { + "type": "string", + "description": "Display name of the team" + }, + "description": { + "type": "string", + "description": "Description of the team" + }, + "owner": { + "type": "string", + "description": "User principal name of the team owner" + }, + "visibility": { + "type": "string", + "enum": ["public", "private"], + "description": "Team visibility" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Team created successfully" + } + } + } + }, + "/api/ListTeamsActivity": { + "get": { + "summary": "List Teams activity", + "description": "List Microsoft Teams user activity", + "parameters": [ + { + "name": "type", + "in": "query", + "required": true, + "schema": { + "type": "string", + "enum": ["TeamsUserActivityUser"] + }, + "description": "Type of Teams activity" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TeamsActivity" + } + } + } + } + } + } + } + }, + "/api/ListTeamsVoice": { + "get": { + "summary": "List Teams voice phone numbers", + "description": "List Microsoft Teams voice phone numbers", + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TeamsVoice" + } + } + } + } + } + } + } + }, + "/api/ExecTeamsVoicePhoneNumberAssignment": { + "post": { + "summary": "Assign Teams voice phone number", + "description": "Assign a phone number to a user or set emergency location", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["PhoneNumber"], + "properties": { + "PhoneNumber": { + "type": "string", + "description": "Phone number to assign" + }, + "PhoneNumberType": { + "type": "string", + "description": "Type of phone number" + }, + "locationOnly": { + "type": "boolean", + "description": "True if only setting emergency location" + }, + "input": { + "type": "string", + "description": "User principal name or location ID" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Operation successful" + } + } + } + }, + "/api/ExecRemoveTeamsVoicePhoneNumberAssignment": { + "post": { + "summary": "Unassign Teams voice phone number", + "description": "Unassign a phone number from a user", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["PhoneNumber", "AssignedTo", "PhoneNumberType"], + "properties": { + "PhoneNumber": { + "type": "string", + "description": "Phone number to unassign" + }, + "AssignedTo": { + "type": "string", + "description": "User the phone number is assigned to" + }, + "PhoneNumberType": { + "type": "string", + "description": "Type of phone number" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Operation successful" + } + } + } + }, + "/api/ListTeamsLisLocation": { + "get": { + "summary": "List Teams emergency locations", + "description": "List Microsoft Teams emergency locations", + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TeamsLocation" + } + } + } + } + } + } + } + }, + "/api/listUsers": { + "get": { + "summary": "List users", + "description": "List users for selection in forms", + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + } + } + } + } + } + } + }, + "/api/ListGraphRequest": { + "get": { + "summary": "List Graph API resources", + "description": "List resources from Microsoft Graph API", + "parameters": [ + { + "name": "Endpoint", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "Graph API endpoint" + }, + { + "name": "$filter", + "in": "query", + "schema": { + "type": "string" + }, + "description": "OData filter" + }, + { + "name": "$top", + "in": "query", + "schema": { + "type": "integer" + }, + "description": "Maximum number of results" + }, + { + "name": "$count", + "in": "query", + "schema": { + "type": "boolean" + }, + "description": "Include count" + }, + { + "name": "$orderby", + "in": "query", + "schema": { + "type": "string" + }, + "description": "Order by field" + }, + { + "name": "$select", + "in": "query", + "schema": { + "type": "string" + }, + "description": "Fields to select" + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Results": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Site": { + "type": "object", + "properties": { + "displayName": { + "type": "string", + "description": "Display name of the site" + }, + "createdDateTime": { + "type": "string", + "format": "date-time", + "description": "Date and time when the site was created" + }, + "ownerPrincipalName": { + "type": "string", + "description": "Principal name of the site owner" + }, + "lastActivityDate": { + "type": "string", + "format": "date-time", + "description": "Date of last activity" + }, + "fileCount": { + "type": "integer", + "description": "Number of files" + }, + "storageUsedInGigabytes": { + "type": "number", + "format": "float", + "description": "Storage used in gigabytes" + }, + "storageAllocatedInGigabytes": { + "type": "number", + "format": "float", + "description": "Storage allocated in gigabytes" + }, + "reportRefreshDate": { + "type": "string", + "format": "date-time", + "description": "Date when the report was refreshed" + }, + "webUrl": { + "type": "string", + "description": "URL of the site" + }, + "description": { + "type": "string", + "description": "Description of the site" + } + } + }, + "Team": { + "type": "object", + "properties": { + "displayName": { + "type": "string", + "description": "Display name of the team" + }, + "description": { + "type": "string", + "description": "Description of the team" + }, + "visibility": { + "type": "string", + "description": "Visibility of the team" + }, + "mailNickname": { + "type": "string", + "description": "Mail nickname of the team" + }, + "id": { + "type": "string", + "description": "ID of the team" + } + } + }, + "TeamsActivity": { + "type": "object", + "properties": { + "UPN": { + "type": "string", + "description": "User principal name" + }, + "LastActive": { + "type": "string", + "format": "date-time", + "description": "Date and time of last activity" + }, + "MeetingCount": { + "type": "integer", + "description": "Number of meetings" + }, + "CallCount": { + "type": "integer", + "description": "Number of calls" + }, + "TeamsChat": { + "type": "integer", + "description": "Number of Teams chats" + } + } + }, + "TeamsVoice": { + "type": "object", + "properties": { + "AssignedTo": { + "type": "string", + "description": "User the phone number is assigned to" + }, + "TelephoneNumber": { + "type": "string", + "description": "Phone number" + }, + "AssignmentStatus": { + "type": "string", + "description": "Assignment status" + }, + "NumberType": { + "type": "string", + "description": "Type of phone number" + }, + "AcquiredCapabilities": { + "type": "string", + "description": "Capabilities of the phone number" + }, + "IsoCountryCode": { + "type": "string", + "description": "ISO country code" + }, + "PlaceName": { + "type": "string", + "description": "Place name" + }, + "ActivationState": { + "type": "string", + "description": "Activation state" + }, + "IsOperatorConnect": { + "type": "boolean", + "description": "Whether the number is operator connect" + }, + "AcquisitionDate": { + "type": "string", + "format": "date-time", + "description": "Date when the number was acquired" + } + } + }, + "TeamsLocation": { + "type": "object", + "properties": { + "Description": { + "type": "string", + "description": "Description of the location" + }, + "LocationId": { + "type": "string", + "description": "ID of the location" + } + } + }, + "User": { + "type": "object", + "properties": { + "displayName": { + "type": "string", + "description": "Display name of the user" + }, + "userPrincipalName": { + "type": "string", + "description": "User principal name" + }, + "id": { + "type": "string", + "description": "ID of the user" + } + } + } + } + } +} \ No newline at end of file diff --git a/Tools/tenant-openapispec.json b/Tools/tenant-openapispec.json new file mode 100644 index 000000000000..80ba16246e40 --- /dev/null +++ b/Tools/tenant-openapispec.json @@ -0,0 +1,1622 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "CIPP Tenant API", + "description": "API for Tenant Management in Cloud Identity and Policy Platform (CIPP)", + "version": "1.0.0" + }, + "servers": [ + { + "url": "/api", + "description": "CIPP API Server" + } + ], + "components": { + "schemas": { + "StandardResponse": { + "type": "object", + "properties": { + "Results": { + "type": "object", + "description": "The results of the operation" + } + } + } + } + }, + "paths": { + "/ListAlertsQueue": { + "get": { + "summary": "List Alerts Queue", + "description": "Retrieves a list of alerts in the queue", + "tags": [ + "Tenant Administration" + ], + "responses": { + "200": { + "description": "Alerts retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "RowKey": { + "type": "string", + "description": "Unique identifier for the alert" + }, + "PartitionKey": { + "type": "string", + "description": "Partition key for the alert" + }, + "LogType": { + "type": "string", + "description": "Type of log" + }, + "RawAlert": { + "type": "object", + "description": "Raw alert data" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/AddAlert": { + "post": { + "summary": "Add Alert", + "description": "Adds a new alert", + "tags": [ + "Tenant Administration" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "tenantFilter": { + "type": "array", + "description": "List of tenants to apply the alert to", + "items": { + "type": "object", + "properties": { + "value": { + "type": "string", + "description": "Tenant ID" + }, + "label": { + "type": "string", + "description": "Tenant name" + } + } + } + }, + "excludedTenants": { + "type": "array", + "description": "List of tenants to exclude from the alert", + "items": { + "type": "object", + "properties": { + "value": { + "type": "string", + "description": "Tenant ID" + }, + "label": { + "type": "string", + "description": "Tenant name" + } + } + } + }, + "logbook": { + "type": "object", + "description": "Log source", + "properties": { + "value": { + "type": "string", + "description": "Log source value" + }, + "label": { + "type": "string", + "description": "Log source label" + } + } + }, + "conditions": { + "type": "array", + "description": "Alert conditions", + "items": { + "type": "object", + "properties": { + "Property": { + "type": "object", + "description": "Property to check", + "properties": { + "value": { + "type": "string", + "description": "Property value" + }, + "label": { + "type": "string", + "description": "Property label" + } + } + }, + "Operator": { + "type": "object", + "description": "Comparison operator", + "properties": { + "value": { + "type": "string", + "description": "Operator value" + }, + "label": { + "type": "string", + "description": "Operator label" + } + } + }, + "Input": { + "type": "object", + "description": "Input value", + "properties": { + "value": { + "type": "string", + "description": "Input value" + } + } + } + } + } + }, + "Actions": { + "type": "array", + "description": "Actions to take", + "items": { + "type": "object", + "properties": { + "value": { + "type": "string", + "description": "Action value" + }, + "label": { + "type": "string", + "description": "Action label" + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Alert added successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/AddScheduledItem": { + "post": { + "summary": "Add Scheduled Item", + "description": "Adds a new scheduled item", + "tags": [ + "Tenant Administration" + ], + "parameters": [ + { + "name": "hidden", + "in": "query", + "description": "Whether to hide the scheduled item", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "DisallowDuplicateName", + "in": "query", + "description": "Whether to disallow duplicate names", + "required": false, + "schema": { + "type": "boolean" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "RowKey": { + "type": "string", + "description": "Unique identifier for the scheduled item" + }, + "tenantFilter": { + "type": "string", + "description": "Tenant to apply the scheduled item to" + }, + "excludedTenants": { + "type": "array", + "description": "List of tenants to exclude from the scheduled item", + "items": { + "type": "object", + "properties": { + "value": { + "type": "string", + "description": "Tenant ID" + }, + "label": { + "type": "string", + "description": "Tenant name" + } + } + } + }, + "Name": { + "type": "string", + "description": "Name of the scheduled item" + }, + "Command": { + "type": "object", + "description": "Command to execute", + "properties": { + "value": { + "type": "string", + "description": "Command value" + } + } + }, + "Parameters": { + "type": "object", + "description": "Parameters for the command" + }, + "ScheduledTime": { + "type": "integer", + "description": "When the job is scheduled to run (Unix timestamp)" + }, + "Recurrence": { + "type": "string", + "description": "How often the job recurs" + }, + "PostExecution": { + "type": "array", + "description": "Actions to take after execution", + "items": { + "type": "object", + "properties": { + "value": { + "type": "string", + "description": "Action value" + }, + "label": { + "type": "string", + "description": "Action label" + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Scheduled item added successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/listCSPLicenses": { + "get": { + "summary": "List CSP Licenses", + "description": "Retrieves a list of CSP licenses", + "tags": [ + "Tenant Reports" + ], + "responses": { + "200": { + "description": "CSP licenses retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Tenant": { + "type": "string", + "description": "Tenant name" + }, + "TenantId": { + "type": "string", + "description": "Tenant ID" + }, + "SubscriptionId": { + "type": "string", + "description": "Subscription ID" + }, + "SkuId": { + "type": "string", + "description": "SKU ID" + }, + "SkuName": { + "type": "string", + "description": "SKU name" + }, + "Status": { + "type": "string", + "description": "Subscription status" + }, + "Quantity": { + "type": "integer", + "description": "License quantity" + }, + "BillingCycle": { + "type": "string", + "description": "Billing cycle" + }, + "RenewalDate": { + "type": "string", + "description": "Renewal date" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecCSPLicense": { + "post": { + "summary": "Execute CSP License Operation", + "description": "Executes an operation on CSP licenses", + "tags": [ + "Tenant Reports" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Action": { + "type": "string", + "description": "Action to perform", + "enum": ["!Add", "!Remove", "!Cancel"] + }, + "sku": { + "type": "string", + "description": "SKU ID" + }, + "add": { + "type": "integer", + "description": "Number of licenses to add" + }, + "Remove": { + "type": "integer", + "description": "Number of licenses to remove" + }, + "SubscriptionIds": { + "type": "string", + "description": "Subscription IDs to cancel" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "CSP license operation executed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListLicenses": { + "get": { + "summary": "List Licenses", + "description": "Retrieves a list of licenses", + "tags": [ + "Tenant Reports" + ], + "responses": { + "200": { + "description": "Licenses retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Tenant": { + "type": "string", + "description": "Tenant name" + }, + "License": { + "type": "string", + "description": "License name" + }, + "CountUsed": { + "type": "integer", + "description": "Number of licenses used" + }, + "CountAvailable": { + "type": "integer", + "description": "Number of licenses available" + }, + "TotalLicenses": { + "type": "integer", + "description": "Total number of licenses" + }, + "TermInfo": { + "type": "object", + "description": "Term information" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListStandards": { + "get": { + "summary": "List Standards", + "description": "Retrieves a list of standards", + "tags": [ + "Tenant Standards" + ], + "responses": { + "200": { + "description": "Standards retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "RowKey": { + "type": "string", + "description": "Unique identifier for the standard" + }, + "Standard": { + "type": "string", + "description": "Standard name" + }, + "Tenant": { + "type": "string", + "description": "Tenant name" + }, + "Enabled": { + "type": "boolean", + "description": "Whether the standard is enabled" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/listStandardTemplates": { + "get": { + "summary": "List Standard Templates", + "description": "Retrieves a list of standard templates", + "tags": [ + "Tenant Standards" + ], + "responses": { + "200": { + "description": "Standard templates retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "GUID": { + "type": "string", + "description": "Unique identifier for the template" + }, + "templateName": { + "type": "string", + "description": "Template name" + }, + "tenantFilter": { + "type": "array", + "description": "List of tenants to apply the template to", + "items": { + "type": "object", + "properties": { + "value": { + "type": "string", + "description": "Tenant ID" + }, + "label": { + "type": "string", + "description": "Tenant name" + } + } + } + }, + "excludedTenants": { + "type": "array", + "description": "List of tenants to exclude from the template", + "items": { + "type": "object", + "properties": { + "value": { + "type": "string", + "description": "Tenant ID" + }, + "label": { + "type": "string", + "description": "Tenant name" + } + } + } + }, + "updatedAt": { + "type": "string", + "description": "When the template was last updated" + }, + "updatedBy": { + "type": "string", + "description": "Who last updated the template" + }, + "runManually": { + "type": "boolean", + "description": "Whether the template is run manually" + }, + "standards": { + "type": "array", + "description": "List of standards in the template", + "items": { + "type": "object" + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecStandardsRun": { + "get": { + "summary": "Execute Standards Run", + "description": "Executes a standards run", + "tags": [ + "Tenant Standards" + ], + "parameters": [ + { + "name": "TemplateId", + "in": "query", + "description": "Template ID to run", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "tenantFilter", + "in": "query", + "description": "Tenant filter", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Standards run executed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/RemoveStandardTemplate": { + "post": { + "summary": "Remove Standard Template", + "description": "Removes a standard template", + "tags": [ + "Tenant Standards" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ID" + ], + "properties": { + "ID": { + "type": "string", + "description": "Template ID to remove" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Standard template removed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/execStandardConvert": { + "post": { + "summary": "Convert Standards", + "description": "Converts legacy standards to the new format", + "tags": [ + "Tenant Standards" + ], + "responses": { + "200": { + "description": "Standards converted successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListNamedLocations": { + "get": { + "summary": "List Named Locations", + "description": "Retrieves a list of named locations", + "tags": [ + "Tenant Conditional Access" + ], + "responses": { + "200": { + "description": "Named locations retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the named location" + }, + "displayName": { + "type": "string", + "description": "Display name" + }, + "@odata.type": { + "type": "string", + "description": "Type of named location" + }, + "includeUnknownCountriesAndRegions": { + "type": "boolean", + "description": "Whether to include unknown countries and regions" + }, + "isTrusted": { + "type": "boolean", + "description": "Whether the location is trusted" + }, + "rangeOrLocation": { + "type": "string", + "description": "Range or location" + }, + "modifiedDateTime": { + "type": "string", + "description": "When the named location was last modified" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecNamedLocation": { + "post": { + "summary": "Execute Named Location Operation", + "description": "Executes an operation on a named location", + "tags": [ + "Tenant Conditional Access" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "namedLocationId", + "change", + "input" + ], + "properties": { + "namedLocationId": { + "type": "string", + "description": "Named location ID" + }, + "change": { + "type": "string", + "description": "Change to make", + "enum": ["addLocation", "removeLocation", "addIp", "removeIp"] + }, + "input": { + "type": "string", + "description": "Input value (country code or IP)" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Named location operation executed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/AddNamedLocation": { + "post": { + "summary": "Add Named Location", + "description": "Adds a new named location", + "tags": [ + "Tenant Conditional Access" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "displayName": { + "type": "string", + "description": "Display name" + }, + "locationType": { + "type": "string", + "description": "Type of location", + "enum": ["country", "ip"] + }, + "countriesAndRegions": { + "type": "array", + "description": "List of countries and regions", + "items": { + "type": "string" + } + }, + "includeUnknownCountriesAndRegions": { + "type": "boolean", + "description": "Whether to include unknown countries and regions" + }, + "ipRanges": { + "type": "array", + "description": "List of IP ranges", + "items": { + "type": "object", + "properties": { + "cidrAddress": { + "type": "string", + "description": "CIDR address" + } + } + } + }, + "isTrusted": { + "type": "boolean", + "description": "Whether the location is trusted" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Named location added successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListConditionalAccessPolicies": { + "get": { + "summary": "List Conditional Access Policies", + "description": "Retrieves a list of conditional access policies", + "tags": [ + "Tenant Conditional Access" + ], + "responses": { + "200": { + "description": "Conditional access policies retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the policy" + }, + "displayName": { + "type": "string", + "description": "Display name" + }, + "state": { + "type": "string", + "description": "State of the policy" + }, + "conditions": { + "type": "object", + "description": "Conditions for the policy" + }, + "grantControls": { + "type": "object", + "description": "Grant controls for the policy" + }, + "sessionControls": { + "type": "object", + "description": "Session controls for the policy" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecCAExclusion": { + "post": { + "summary": "Execute Conditional Access Exclusion", + "description": "Executes a conditional access exclusion", + "tags": [ + "Tenant Conditional Access" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "tenantFilter": { + "type": "object", + "description": "Tenant filter", + "properties": { + "value": { + "type": "string", + "description": "Tenant ID" + }, + "label": { + "type": "string", + "description": "Tenant name" + } + } + }, + "user": { + "type": "object", + "description": "User to exclude", + "properties": { + "value": { + "type": "string", + "description": "User ID" + }, + "label": { + "type": "string", + "description": "User name" + } + } + }, + "policy": { + "type": "object", + "description": "Policy to exclude from", + "properties": { + "value": { + "type": "string", + "description": "Policy ID" + }, + "label": { + "type": "string", + "description": "Policy name" + } + } + }, + "startDate": { + "type": "string", + "description": "Start date for the exclusion" + }, + "endDate": { + "type": "string", + "description": "End date for the exclusion" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Conditional access exclusion executed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListGraphRequest": { + "get": { + "summary": "List Graph Request", + "description": "Retrieves data from Microsoft Graph API", + "tags": [ + "Tenant Administration" + ], + "parameters": [ + { + "name": "Endpoint", + "in": "query", + "description": "Graph API endpoint", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "$select", + "in": "query", + "description": "Fields to select", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "$count", + "in": "query", + "description": "Whether to include count", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "$top", + "in": "query", + "description": "Number of results to return", + "required": false, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "Graph request executed successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Results": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListAuditLogs": { + "get": { + "summary": "List Audit Logs", + "description": "Retrieves a list of audit logs", + "tags": [ + "Tenant Administration" + ], + "parameters": [ + { + "name": "RelativeTime", + "in": "query", + "description": "Relative time filter", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "StartDate", + "in": "query", + "description": "Start date filter", + "required": false, + "schema": { + "type": "string", + "format": "date" + } + }, + { + "name": "EndDate", + "in": "query", + "description": "End date filter", + "required": false, + "schema": { + "type": "string", + "format": "date" + } + } + ], + "responses": { + "200": { + "description": "Audit logs retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Timestamp": { + "type": "string", + "description": "When the log entry was created" + }, + "Tenant": { + "type": "string", + "description": "Tenant name" + }, + "Title": { + "type": "string", + "description": "Log title" + }, + "LogId": { + "type": "string", + "description": "Unique identifier for the log" + }, + "Actions": { + "type": "string", + "description": "Actions taken" + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecListBackup": { + "get": { + "summary": "List Backups", + "description": "Retrieves a list of backups", + "tags": [ + "Tenant Backup" + ], + "parameters": [ + { + "name": "tenantFilter", + "in": "query", + "description": "Tenant filter", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Backups retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "BackupName": { + "type": "string", + "description": "Name of the backup" + }, + "Timestamp": { + "type": "string", + "description": "When the backup was created" + }, + "Backup": { + "type": "string", + "description": "The backup data (JSON string)" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListCSPsku": { + "get": { + "summary": "List CSP SKUs", + "description": "Retrieves a list of CSP SKUs", + "tags": [ + "Tenant Administration" + ], + "responses": { + "200": { + "description": "CSP SKUs retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "sku": { + "type": "string", + "description": "SKU ID" + }, + "name": { + "type": "array", + "description": "SKU names", + "items": { + "type": "object", + "properties": { + "value": { + "type": "string", + "description": "SKU name" + } + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListCommunityRepos": { + "get": { + "summary": "List Community Repositories", + "description": "Retrieves a list of community repositories", + "tags": [ + "Tenant Standards" + ], + "parameters": [ + { + "name": "WriteAccess", + "in": "query", + "description": "Whether to only include repositories with write access", + "required": false, + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "Community repositories retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "FullName": { + "type": "string", + "description": "Full name of the repository" + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecCommunityRepo": { + "post": { + "summary": "Execute Community Repository Operation", + "description": "Executes an operation on a community repository", + "tags": [ + "Tenant Standards" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "Action", + "GUID", + "FullName", + "Message" + ], + "properties": { + "Action": { + "type": "string", + "description": "Action to perform", + "enum": ["UploadTemplate"] + }, + "GUID": { + "type": "string", + "description": "Template GUID" + }, + "FullName": { + "type": "string", + "description": "Repository full name" + }, + "Message": { + "type": "string", + "description": "Commit message" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Community repository operation executed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListExtensionsConfig": { + "get": { + "summary": "List Extensions Configuration", + "description": "Retrieves the configuration for extensions", + "tags": [ + "Tenant Administration" + ], + "responses": { + "200": { + "description": "Extensions configuration retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "Enabled": { + "type": "boolean", + "description": "Whether the extension is enabled" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + } + } +} \ No newline at end of file diff --git a/Tools/tools-openapispec.json b/Tools/tools-openapispec.json new file mode 100644 index 000000000000..7d85f7a40e4a --- /dev/null +++ b/Tools/tools-openapispec.json @@ -0,0 +1,665 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "CIPP Tools API", + "description": "API for Tools in Cloud Identity and Policy Platform (CIPP)", + "version": "1.0.0" + }, + "servers": [ + { + "url": "/api", + "description": "CIPP API Server" + } + ], + "components": { + "schemas": { + "StandardResponse": { + "type": "object", + "properties": { + "Results": { + "type": "object", + "description": "The results of the operation" + } + } + } + } + }, + "paths": { + "/ListBreachesAccount": { + "get": { + "summary": "List Breaches for Account", + "description": "Retrieves a list of breaches for a specific account (email or domain)", + "tags": [ + "Breach Lookup" + ], + "parameters": [ + { + "name": "account", + "in": "query", + "description": "Email address or domain name to check for breaches", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Breaches retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Title": { + "type": "string", + "description": "Title of the breach" + }, + "LogoPath": { + "type": "string", + "description": "Path to the breach logo" + }, + "password": { + "type": "string", + "description": "Partial password if available" + }, + "Description": { + "type": "string", + "description": "Description of the breach" + }, + "Domain": { + "type": "string", + "description": "Domain associated with the breach" + }, + "DataClasses": { + "type": "array", + "description": "Types of data leaked in the breach", + "items": { + "type": "string" + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListBreachesTenant": { + "get": { + "summary": "List Breaches for Tenant", + "description": "Retrieves a list of breaches for a specific tenant", + "tags": [ + "Breach Lookup" + ], + "parameters": [ + { + "name": "tenantFilter", + "in": "query", + "description": "Tenant ID to filter breaches", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Tenant breaches retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "Email address associated with the breach" + }, + "password": { + "type": "string", + "description": "Partial password if available" + }, + "sources": { + "type": "string", + "description": "Sources of the breach data" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecBreachSearch": { + "get": { + "summary": "Execute Breach Search", + "description": "Executes a breach search for a tenant", + "tags": [ + "Breach Lookup" + ], + "parameters": [ + { + "name": "tenantFilter", + "in": "query", + "description": "Tenant ID to search for breaches", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Breach search executed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListExtensionsConfig": { + "get": { + "summary": "List Extensions Configuration", + "description": "Retrieves the configuration for extensions", + "tags": [ + "Community Repositories" + ], + "responses": { + "200": { + "description": "Extensions configuration retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "GitHub": { + "type": "object", + "properties": { + "Enabled": { + "type": "boolean", + "description": "Whether GitHub integration is enabled" + } + } + } + }, + "additionalProperties": { + "type": "object", + "properties": { + "Enabled": { + "type": "boolean", + "description": "Whether the extension is enabled" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecGitHubAction": { + "get": { + "summary": "Execute GitHub Action (GET)", + "description": "Executes a GitHub action with GET method", + "tags": [ + "Community Repositories" + ], + "parameters": [ + { + "name": "Action", + "in": "query", + "description": "Action to perform", + "required": true, + "schema": { + "type": "string", + "enum": ["GetBranches", "GetFileTree", "GetFileContents", "GetOrgs"] + } + }, + { + "name": "FullName", + "in": "query", + "description": "Full name of the repository (owner/repo)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Branch", + "in": "query", + "description": "Branch name", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Path", + "in": "query", + "description": "File path", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "GitHub action executed successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Results": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + }, + "post": { + "summary": "Execute GitHub Action (POST)", + "description": "Executes a GitHub action with POST method", + "tags": [ + "Community Repositories" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "Action" + ], + "properties": { + "Action": { + "type": "string", + "description": "Action to perform", + "enum": ["CreateRepo", "Search", "GetFileContents"] + }, + "Type": { + "type": "string", + "description": "Type of repository (user or org)", + "enum": ["user", "org", "repositories"] + }, + "Name": { + "type": "string", + "description": "Repository name" + }, + "Org": { + "type": "string", + "description": "Organization name" + }, + "Description": { + "type": "string", + "description": "Repository description" + }, + "Private": { + "type": "boolean", + "description": "Whether the repository is private" + }, + "Repository": { + "type": "string", + "description": "Repository name for search" + }, + "User": { + "type": "string", + "description": "User name for search" + }, + "SearchTerm": { + "type": "array", + "description": "Search terms", + "items": { + "type": "string" + } + }, + "FullName": { + "type": "string", + "description": "Full name of the repository (owner/repo)" + }, + "Path": { + "type": "string", + "description": "File path" + }, + "Branch": { + "type": "string", + "description": "Branch name" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "GitHub action executed successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Results": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ListCommunityRepos": { + "get": { + "summary": "List Community Repositories", + "description": "Retrieves a list of community repositories", + "tags": [ + "Community Repositories" + ], + "responses": { + "200": { + "description": "Community repositories retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "Results": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Name": { + "type": "string", + "description": "Repository name" + }, + "Owner": { + "type": "string", + "description": "Repository owner" + }, + "URL": { + "type": "string", + "description": "Repository URL" + }, + "Visibility": { + "type": "string", + "description": "Repository visibility (public/private)" + }, + "WriteAccess": { + "type": "boolean", + "description": "Whether the user has write access to the repository" + }, + "UploadBranch": { + "type": "string", + "description": "Branch used for uploads" + }, + "FullName": { + "type": "string", + "description": "Full name of the repository (owner/repo)" + }, + "DefaultBranch": { + "type": "string", + "description": "Default branch of the repository" + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/ExecCommunityRepo": { + "post": { + "summary": "Execute Community Repository Operation", + "description": "Executes an operation on a community repository", + "tags": [ + "Community Repositories" + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "Action" + ], + "properties": { + "Action": { + "type": "string", + "description": "Action to perform", + "enum": ["Add", "Delete", "SetBranch", "ImportTemplate"] + }, + "Id": { + "type": "string", + "description": "Repository ID" + }, + "Branch": { + "type": "string", + "description": "Branch name" + }, + "FullName": { + "type": "string", + "description": "Full name of the repository (owner/repo)" + }, + "Path": { + "type": "string", + "description": "File path for template import" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Community repository operation executed successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/AddScheduledItem": { + "post": { + "summary": "Add Scheduled Item", + "description": "Adds a new scheduled item", + "tags": [ + "Template Library" + ], + "parameters": [ + { + "name": "DisallowDuplicateName", + "in": "query", + "description": "Whether to disallow duplicate names", + "required": false, + "schema": { + "type": "boolean" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "TenantFilter": { + "type": "string", + "description": "Tenant to apply the scheduled item to" + }, + "Name": { + "type": "string", + "description": "Name of the scheduled item" + }, + "Command": { + "type": "object", + "description": "Command to execute", + "properties": { + "value": { + "type": "string", + "description": "Command value" + } + } + }, + "Parameters": { + "type": "object", + "description": "Parameters for the command", + "properties": { + "TemplateSettings": { + "type": "object", + "description": "Template settings" + } + } + }, + "ScheduledTime": { + "type": "integer", + "description": "When the job is scheduled to run (Unix timestamp)" + }, + "Recurrence": { + "type": "object", + "description": "How often the job recurs", + "properties": { + "value": { + "type": "string", + "description": "Recurrence value" + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Scheduled item added successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StandardResponse" + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal server error" + } + } + } + } + } +} \ No newline at end of file diff --git a/version_latest.txt b/version_latest.txt index 0e79152459e0..fbb9ea12de3a 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -8.1.1 +8.2.0