GraphEssentials.psm1
function Convert-Office365License { <# .SYNOPSIS Converts Office 365 licenses between their names and SKUs. .DESCRIPTION This function allows for the conversion of Office 365 licenses between their names and SKUs. It provides flexibility to handle multiple values for licenses. .PARAMETER License Specifies the Office 365 license SKU or name to convert. Supports multiple values. .PARAMETER ToSku Indicates whether to convert the license name to SKU. .PARAMETER Separator Specifies the separator to use when returning multiple values. .PARAMETER ReturnArray Indicates whether to return the result as an array. .EXAMPLE Convert-Office365License -License 'VISIOCLIENT','PROJECTONLINE_PLAN_1','test','tenant:VISIOCLIENT' Converts the specified licenses to their corresponding SKUs. .EXAMPLE Convert-Office365License -License "Office 365 A3 for faculty", "Project Plan 3 (for Department)", 'test' -ToSku Converts the specified license names to their corresponding SKUs. .NOTES For more information on Office 365 licensing, refer to: https://learn.microsoft.com/en-us/azure/active-directory/enterprise-users/licensing-service-plan-reference #> [CmdletBinding()] param( [Parameter(Position = 0, ValueFromPipeline)][Array] $License, [alias('SKU')][switch] $ToSku, [string] $Separator = ', ', [switch] $ReturnArray ) Begin { $O365SKU = [ordered] @{ 'AAD_BASIC' = "Azure Active Directory Basic" 'AAD_BASIC_EDU' = "Azure Active Directory Basic for Education" 'AAD_EDU' = "Azure Active Directory for Education" 'AAD_PREMIUM' = "Azure Active Directory Premium P1" 'AAD_PREMIUM_FACULTY' = "Azure Active Directory Premium P1 for Faculty" 'AAD_PREMIUM_P2' = "Azure Active Directory Premium P2" 'AAD_SMB' = "Azure Active Directory" 'ADALLOM_FOR_AATP' = "SecOps Investigation for MDI" 'ADALLOM_O365' = "Office 365 Cloud App Security" 'ADALLOM_S_DISCOVERY' = "CLOUD APP SECURITY DISCOVERY" 'ADALLOM_S_O365' = "Office 365 Cloud App Security" 'ADALLOM_S_STANDALONE' = "MICROSOFT CLOUD APP SECURITY" 'ADALLOM_S_STANDALONE_DOD' = "Microsoft Defender for Cloud Apps for DOD" 'ADALLOM_STANDALONE' = "Microsoft Cloud App Security" 'ADV_COMMS' = "Advanced Communications" 'ATA' = "Microsoft Defender for Identity" 'ATP_ENTERPRISE' = "Microsoft Defender for Office 365 (Plan 1)" 'ATP_ENTERPRISE_FACULTY' = "Microsoft Defender for Office 365 (Plan 1) Faculty" 'ATP_ENTERPRISE_GOV' = "Microsoft Defender for Office 365 (Plan 1) GCC" 'AX7_USER_TRIAL' = "Microsoft Dynamics AX7 User Trial" 'BI_AZURE_P_2_GOV' = "Power BI Pro for Government" 'BI_AZURE_P0' = "Power BI (free)" 'BI_AZURE_P1' = "Microsoft Power BI Reporting and Analytics Plan 1" 'BI_AZURE_P2' = "Power BI Pro" 'BI_AZURE_P3' = "Power BI Premium Per User" 'BPOS_S_DlpAddOn' = "Data Loss Prevention" 'BPOS_S_TODO_1' = "To-Do (Plan 1)" 'BPOS_S_TODO_2' = "To-Do (Plan 2)" 'BPOS_S_TODO_3' = "To-Do (Plan 3)" 'BPOS_S_TODO_FIRSTLINE' = "To-Do (Firstline)" 'CCIBOTS_PRIVPREV_VIRAL' = "Power Virtual Agents Viral Trial" 'CDS_ATTENDED_RPA' = "Common Data Service Attended RPA" 'CDS_CUSTOMER_INSIGHTS' = "Common Data Service for Customer Insights" 'CDS_CUSTOMER_INSIGHTS_BASE' = "Dataverse for Customer Insights�BASE" 'CDS_CUSTOMER_INSIGHTS_TRIAL' = "Common Data Service for Customer Insights Trial" 'CDS_DB_CAPACITY' = "Common Data Service Database Capacity" 'CDS_DB_CAPACITY_GOV' = "Common Data Service Database Capacity for Government" 'CDS_FILE_CAPACITY' = "Common Data Service for Apps File Capacity" 'CDS_Flow_Business_Process' = "Common data service for Flow per business process plan" 'CDS_FORM_PRO_USL' = "Common Data Service" 'CDS_LOG_CAPACITY' = "Common Data Service Log Capacity" 'CDS_O365_E5_KM' = "Common Data Service for SharePoint Syntex" 'CDS_O365_F1' = "Common Data Service for Teams" 'CDS_O365_F1_GCC' = "Common Data Service for Teams_F1 GCC" 'CDS_O365_P1' = "COMMON DATA SERVICE FOR TEAMS_P1" 'CDS_O365_P1_GCC' = "Common Data Service for Teams_P1 GCC" 'CDS_O365_P2' = "Common Data Service for Teams" 'CDS_O365_P2_GCC' = "COMMON DATA SERVICE FOR TEAMS_P2 GCC" 'CDS_O365_P3' = "Common Data Service for Teams" 'CDS_O365_P3_GCC' = "Common Data Service for Teams" 'CDS_PER_APP' = "CDS PowerApps per app plan" 'CDS_PER_APP_IWTRIAL' = "CDS Per app baseline access" 'CDS_POWERAPPS_PORTALS_LOGIN' = "Common Data Service Power Apps Portals Login Capacity" 'CDS_POWERAPPS_PORTALS_LOGIN_GCC' = "Common Data Service Power Apps Portals Login Capacity for GCC" 'CDS_POWERAPPS_PORTALS_PAGEVIEW' = "CDS PowerApps Portals page view capacity add-on" 'CDS_POWERAPPS_PORTALS_PAGEVIEW_GCC' = "CDS PowerApps Portals page view capacity add-on for GCC" 'CDS_REMOTE_ASSIST' = "Common Data Service for Remote Assist" 'CDS_UNATTENDED_RPA' = "Common Data Service Unattended RPA" 'CDS_VIRTUAL_AGENT_BASE' = "Common Data Service for Virtual Agent Base" 'CDS_VIRTUAL_AGENT_USL' = "Common Data Service" 'CDSAICAPACITY' = "AI Builder Capacity add-on" 'CDSAICAPACITY_PERAPP' = "AI Builder capacity Per App add-on" 'CDSAICAPACITY_PERUSER' = "AI Builder capacity Per User add-on" 'CDSAICAPACITY_PERUSER_NEW' = "AI Builder capacity Per User add-on" 'CMPA_addon' = "Compliance Manager Premium Assessment Add-On" 'CMPA_addon_GCC' = "Compliance Manager Premium Assessment Add-On for GCC" 'COMMUNICATIONS_COMPLIANCE' = "Microsoft Communications Compliance" 'COMMUNICATIONS_DLP' = "Microsoft Communications DLP" 'COMPLIANCE_MANAGER_PREMIUM_ASSESSMENT_ADDON' = "Compliance Manager Premium Assessment Add-On" 'Content_Explorer' = "Information Protection and Governance Analytics - Premium" 'ContentExplorer_Standard' = "Information Protection and Governance Analytics � Standard" 'CORTEX' = "Microsoft Viva Topics" 'CPC_1' = "Windows 365 Enterprise 2 vCPU 4 GB 128 GB" 'CPC_2' = "Windows 365 Enterprise 2 vCPU 8 GB 128 GB" 'CPC_B_1C_2RAM_64GB' = "Windows 365 Business 1 vCPU 2 GB 64 GB" 'CPC_B_2C_4RAM_128GB' = "Windows 365 Business 2 vCPU 4 GB 128 GB" 'CPC_B_2C_4RAM_256GB' = "Windows 365 Business 2 vCPU 4 GB 256 GB" 'CPC_B_2C_4RAM_64GB' = "Windows 365 Business 2 vCPU 4 GB 64 GB" 'CPC_B_2C_8RAM_128GB' = "Windows 365 Business 2 vCPU 8 GB 128 GB" 'CPC_B_2C_8RAM_256GB' = "Windows 365 Business 2 vCPU 8 GB 256 GB" 'CPC_B_4C_16RAM_128GB' = "Windows 365 Business 4 vCPU 16 GB 128 GB" 'CPC_B_4C_16RAM_128GB_WHB' = "Windows 365 Business 4 vCPU 16 GB 128 GB (with Windows Hybrid Benefit)" 'CPC_B_4C_16RAM_256GB' = "Windows 365 Business 4 vCPU 16 GB 256 GB" 'CPC_B_4C_16RAM_512GB' = "Windows 365 Business 4 vCPU 16 GB 512 GB" 'CPC_B_8C_32RAM_128GB' = "Windows 365 Business 8 vCPU 32 GB 128 GB" 'CPC_B_8C_32RAM_256GB' = "Windows 365 Business 8 vCPU 32 GB 256 GB" 'CPC_B_8C_32RAM_512GB' = "Windows 365 Business 8 vCPU 32 GB 512 GB" 'CPC_E_1C_2GB_64GB' = "Windows 365 Enterprise 1 vCPU 2 GB 64 GB" 'CPC_E_2C_4GB_128GB' = "Windows 365 Enterprise 2 vCPU 4 GB 128 GB" 'CPC_E_2C_4GB_256GB' = "Windows 365 Enterprise 2 vCPU 4 GB 256 GB" 'CPC_E_2C_4GB_64GB' = "Windows 365 Enterprise 2 vCPU 4 GB 64 GB" 'CPC_E_2C_8GB_128GB' = "Windows 365 Enterprise 2 vCPU 8 GB 128 GB" 'CPC_E_2C_8GB_256GB' = "Windows 365 Enterprise 2 vCPU 8 GB 256 GB" 'CPC_E_4C_16GB_128GB' = "Windows 365 Enterprise 4 vCPU 16 GB 128 GB" 'CPC_E_4C_16GB_256GB' = "Windows 365 Enterprise 4 vCPU 16 GB 256 GB" 'CPC_E_4C_16GB_512GB' = "Windows 365 Enterprise 4 vCPU 16 GB 512 GB" 'CPC_E_8C_32GB_128GB' = "Windows 365 Enterprise 8 vCPU 32 GB 128 GB" 'CPC_E_8C_32GB_256GB' = "Windows 365 Enterprise 8 vCPU 32 GB 256 GB" 'CPC_E_8C_32GB_512GB' = "Windows 365 Enterprise 8 vCPU 32 GB 512 GB" 'CPC_LVL_1' = "Windows 365 Enterprise 2 vCPU 4 GB 128 GB (Preview)" 'CPC_LVL_2' = "Windows 365 Enterprise 2 vCPU 8 GB 128 GB (Preview)" 'CPC_LVL_3' = "Windows 365 Enterprise 4 vCPU 16 GB 256 GB (Preview)" 'CPC_S_2C_4GB_128GB' = "Windows 365 Shared Use 2 vCPU 4 GB 128 GB" 'CPC_S_2C_4GB_256GB' = "Windows 365 Shared Use 2 vCPU 4 GB 256 GB" 'CPC_S_2C_4GB_64GB' = "Windows 365 Shared Use 2 vCPU 4 GB 64 GB" 'CPC_S_2C_8GB_128GB' = "Windows 365 Shared Use 2 vCPU 8 GB 128 GB" 'CPC_S_2C_8GB_256GB' = "Windows 365 Shared Use 2 vCPU 8 GB 256 GB" 'CPC_S_4C_16GB_128GB' = "Windows 365 Shared Use 4 vCPU 16 GB 128 GB" 'CPC_S_4C_16GB_256GB' = "Windows 365 Shared Use 4 vCPU 16 GB 256 GB" 'CPC_S_4C_16GB_512GB' = "Windows 365 Shared Use 4 vCPU 16 GB 512 GB" 'CPC_S_8C_32GB_128GB' = "Windows 365 Shared Use 8 vCPU 32 GB 128 GB" 'CPC_S_8C_32GB_256GB' = "Windows 365 Shared Use 8 vCPU 32 GB 256 GB" 'CPC_S_8C_32GB_512GB' = "Windows 365 Shared Use 8 vCPU 32 GB 512 GB" 'CPC_SS_2' = "Windows 365 Business 2 vCPU, 8 GB, 128 GB" 'CRM_AUTO_ROUTING_ADDON' = "Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization" 'CRM_AUTO_ROUTING_ENGINE_ADDON' = "Field Service � Automated Routing Engine Add-On" 'CRM_HYBRIDCONNECTOR' = "Dynamics 365 Hybrid Connector" 'CRM_ONLINE_PORTAL' = "Dynamics 365 Enterprise Edition - Additional Portal (Qualified Offer)" 'CRMINSTANCE' = "Dynamics 365 - Additional Production Instance (Qualified Offer)" 'CRMPLAN2' = "Microsoft Dynamics CRM Online Basic" 'CRMSTANDARD' = "Microsoft Dynamics CRM Online" 'CRMSTORAGE' = "Dynamics 365 - Additional Database Storage (Qualified Offer)" 'CRMTESTINSTANCE' = "Dynamics 365 - Additional Non-Production Instance (Qualified Offer)" 'CUSTOMER_KEY' = "Microsoft Customer Key" 'CUSTOMER_VOICE_ADDON' = "Dynamics Customer Voice Add-On" 'Customer_Voice_Base' = "Dynamics 365 Customer Voice Base Plan" 'Customer_Voice_Customer_Insights' = "Microsoft Dynamics 365 Customer Voice for Customer Insights App" 'CUSTOMER_VOICE_DYN365_VIRAL_TRIAL' = "Customer Voice for Dynamics 365 vTrial" 'D365_AssetforSCM' = "Asset Maintenance Add-in" 'D365_CSI_EMBED_CE' = "Dynamics 365 Customer Service Insights for CE Plan" 'D365_CSI_EMBED_CSEnterprise' = "Dynamics 365 Customer Service Insights for CS Enterprise" 'D365_CUSTOMER_SERVICE_ENT_ATTACH' = "Dynamics 365 for Customer Service Enterprise Attach to Qualifying Dynamics 365 Base Offer A" 'D365_FIELD_SERVICE_ATTACH' = "Dynamics 365 for Field Service Attach to Qualifying Dynamics 365 Base Offer" 'D365_Finance' = "Microsoft Dynamics 365 for Finance" 'D365_IOTFORSCM' = "Iot Intelligence Add-in for D365 Supply Chain Management" 'D365_IOTFORSCM_ADDITIONAL' = "IoT Intelligence Add-in Additional Machines" 'D365_MARKETING_USER' = "Dynamics 365 for Marketing USL" 'D365_ProjectOperations' = "Dynamics 365 Project Operations" 'D365_ProjectOperationsCDS' = "Dynamics 365 Project Operations CDS" 'D365_SALES_ENT_ATTACH' = "Dynamics 365 Sales Enterprise Attach to Qualifying Dynamics 365 Base Offer" 'D365_SALES_PRO' = "Dynamics 365 For Sales Professional" 'D365_SALES_PRO_ATTACH' = "Dynamics 365 Sales Professional Attach to Qualifying Dynamics 365 Base Offer" 'D365_SALES_PRO_IW' = "Dynamics 365 For Sales Professional Trial" 'D365_SALES_PRO_IW_Trial' = "Dynamics 365 for Sales Professional Trial" 'D365_SCM' = "DYNAMICS 365 FOR SUPPLY CHAIN MANAGEMENT" 'DATA_INVESTIGATIONS' = "Microsoft Data Investigations" 'DATAVERSE_FOR_POWERAUTOMATE_DESKTOP' = "Dataverse for PAD" 'DATAVERSE_POWERAPPS_PER_APP_NEW' = "Dataverse for Power Apps per app" 'DDYN365_CDS_DYN_P2' = "COMMON DATA SERVICE" 'DEFENDER_ENDPOINT_P1' = "Microsoft Defender for Endpoint P1" 'DEFENDER_ENDPOINT_P1_EDU' = "Microsoft Defender for Endpoint P1 for EDU" 'Defender_Threat_Intelligence' = "Defender Threat Intelligence" 'Deskless' = "Microsoft StaffHub" 'DESKLESSPACK' = "Office 365 F3" 'DEVELOPERPACK' = "Office 365 E3 Developer" 'DEVELOPERPACK_E5' = "Microsoft 365 E5 Developer (without Windows and Audio Conferencing)" 'DYN365_ ENTERPRISE _RELATIONSHIP_SALES' = "Microsoft Relationship Sales solution" 'DYN365_AI_SERVICE_INSIGHTS' = "Dynamics 365 Customer Service Insights Trial" 'DYN365_ASSETMANAGEMENT' = "Dynamics 365 Asset Management Addl Assets" 'DYN365_BUSCENTRAL_ADD_ENV_ADDON' = "Dynamics 365 Business Central Additional Environment Addon" 'DYN365_BUSCENTRAL_DB_CAPACITY' = "Dynamics 365 Business Central Database Capacity" 'DYN365_BUSCENTRAL_ENVIRONMENT' = "Dynamics 365 Business Central Additional Environment Addon" 'DYN365_BUSCENTRAL_ESSENTIAL' = "Dynamics 365 Business Central Essentials" 'DYN365_BUSCENTRAL_PREMIUM' = "Dynamics 365 Business Central Premium" 'DYN365_BUSCENTRAL_TEAM_MEMBER' = "Dynamics 365 Business Central Team Members" 'DYN365_BUSINESS_MARKETING' = "Dynamics 365 for Marketing Business Edition" 'DYN365_CDS_CCI_BOTS' = "Common Data Service for CCI Bots" 'DYN365_CDS_DEV_VIRAL' = "Common Data Service - DEV VIRAL" 'DYN365_CDS_DYN_APPS' = "Common Data Service" 'DYN365_CDS_FINANCE' = "Common Data Service for Dynamics 365 Finance" 'DYN365_CDS_FOR_PROJECT_P1' = "COMMON DATA SERVICE FOR PROJECT P1" 'DYN365_CDS_FORMS_PRO' = "Common Data Service" 'DYN365_CDS_GUIDES' = "Common Data Service" 'DYN365_CDS_O365_F1' = "Common Data Service" 'DYN365_CDS_O365_F1_GCC' = "Common Data Service - O365 F1" 'DYN365_CDS_O365_P1' = "Common Data Service - O365 P1" 'DYN365_CDS_O365_P1_GCC' = "Common Data Service - O365 P1 GCC" 'DYN365_CDS_O365_P2' = "Common Data Service" 'DYN365_CDS_O365_P2_GCC' = "COMMON DATA SERVICE - O365 P2 GCC" 'DYN365_CDS_O365_P3' = "Common Data Service" 'DYN365_CDS_O365_P3_GCC' = "Common Data Service" 'DYN365_CDS_P1_GOV' = "Common Data Service for Government" 'DYN365_CDS_P2' = "Common Data Service - P2" 'DYN365_CDS_P2_GOV' = "Common Data Service for Government" 'DYN365_CDS_PROJECT' = "Common Data Service for Project" 'DYN365_CDS_SUPPLYCHAINMANAGEMENT' = "COMMON DATA SERVICE FOR DYNAMICS 365 SUPPLY CHAIN MANAGEMENT" 'DYN365_CDS_VIRAL' = "Common Data Service" 'DYN365_CS_CHAT' = "Dynamics 365 for Customer Service Chat" 'DYN365_CS_CHAT_FPA' = "Dynamics 365 Customer Service Chat Application Integration" 'DYN365_CS_ENTERPRISE_VIRAL_TRIAL' = "Dynamics 365 Customer Service Enterprise vTrial" 'DYN365_CS_MESSAGING_TPS' = "Dynamics 365 Customer Service Digital Messaging add-on" 'DYN365_CS_MESSAGING_VIRAL_TRIAL' = "Dynamics 365 Customer Service Digital Messaging vTrial" 'DYN365_CS_VOICE' = "Dynamics 365 for Customer Service Voice Add-in" 'DYN365_CS_VOICE_VIRAL_TRIAL' = "Dynamics 365 Customer Service Voice vTrial" 'DYN365_CUSTOMER_INSIGHTS_ATTACH' = "Dynamics 365 Customer Insights Attach" 'DYN365_CUSTOMER_INSIGHTS_BASE' = "Dynamics 365 Customer Insights Standalone" 'DYN365_CUSTOMER_INSIGHTS_ENGAGEMENT_INSIGHTS_BASE' = "Dynamics 365 Customer Insights Engagement Insights" 'DYN365_CUSTOMER_INSIGHTS_ENGAGEMENT_INSIGHTS_BASE_TRIAL' = "Dynamics 365 Customer Insights Engagement Insights Viral" 'DYN365_CUSTOMER_INSIGHTS_VIRAL' = "Dynamics 365 Customer Insights vTrial" 'DYN365_CUSTOMER_SERVICE_PRO' = "Dynamics 365 Customer Service Professional" 'DYN365_CUSTOMER_VOICE_ADDON' = "Dynamics 365 Customer Voice Additional Responses" 'DYN365_CUSTOMER_VOICE_BASE' = "Dynamics 365 Customer Voice" 'DYN365_ENTERPRISE_CASE_MANAGEMENT' = "Dynamics 365 for Case Management Enterprise Edition" 'DYN365_ENTERPRISE_CUSTOMER_SERVICE' = "Dynamics 365 for Customer Service Enterprise Edition" 'DYN365_ENTERPRISE_FIELD_SERVICE' = "Dynamics 365 for Field Service Enterprise Edition" 'DYN365_ENTERPRISE_P1' = "Dynamics 365 P1" 'DYN365_ENTERPRISE_P1_IW' = "Dynamics 365 P1 Tria for Information Workers" 'DYN365_ENTERPRISE_PLAN1' = "Dynamics 365 Customer Engagement Plan" 'DYN365_ENTERPRISE_SALES' = "Dynamics 365 for Sales Enterprise Edition" 'DYN365_ENTERPRISE_SALES_CUSTOMERSERVICE' = "Dynamics 365 for Sales and Customer Service Enterprise Edition" 'DYN365_Enterprise_Talent_Attract_TeamMember' = "DYNAMICS 365 FOR TALENT - ATTRACT EXPERIENCE TEAM MEMBER" 'DYN365_Enterprise_Talent_Onboard_TeamMember' = "DYNAMICS 365 FOR TALENT - ONBOARD EXPERIENCE" 'DYN365_ENTERPRISE_TEAM_MEMBERS' = "Dynamics 365 for Team Members Enterprise Edition" 'DYN365_FINANCE' = "Dynamics 365 Finance" 'DYN365_FINANCIALS_ACCOUNTANT' = "Dynamics 365 Business Central External Accountant" 'DYN365_FINANCIALS_ACCOUNTANT_SKU' = "Dynamics 365 Business Central External Accountant" 'DYN365_FINANCIALS_BUSINESS' = "Dynamics 365 for Business Central Essentials" 'DYN365_FINANCIALS_BUSINESS_SKU' = "Dynamics 365 for Financials Business Edition" 'DYN365_FINANCIALS_TEAM_MEMBERS' = "Dynamics 365 for Team Members" 'DYN365_FS_ENTERPRISE_VIRAL_TRIAL' = "Dynamics 365 Field Service Enterprise vTrial" 'DYN365_IOT_INTELLIGENCE_ADDL_MACHINES' = "Sensor Data Intelligence Additional Machines Add-in for Dynamics 365 Supply Chain Management" 'DYN365_IOT_INTELLIGENCE_SCENARIO' = "Sensor Data Intelligence Scenario Add-in for Dynamics 365 Supply Chain Management" 'DYN365_MARKETING_50K_CONTACT_ADDON' = "Dynamics 365 for Marketing 50K Addnl Contacts" 'DYN365_MARKETING_APP' = "Dynamics 365 for Marketing" 'DYN365_MARKETING_APP_ATTACH' = "Dynamics 365 for Marketing Attach" 'DYN365_MARKETING_APPLICATION_ADDON' = "Dynamics 365 for Marketing Additional Application" 'DYN365_MARKETING_CONTACT_ADDON_T3' = "Dynamics 365 for Marketing Addnl Contacts Tier 3" 'DYN365_MARKETING_CONTACT_ADDON_T5' = "Dynamics 365 for Marketing Addnl Contacts Tier 5" 'DYN365_MARKETING_MSE_USER' = "Dynamics 365 for Marketing MSE User" 'DYN365_MARKETING_SANDBOX_APPLICATION_ADDON' = "Dynamics 365 for Marketing Additional Non-Prod Application" 'DYN365_MARKETING_USER' = "Dynamics 365 for Marketing USL" 'DYN365_REGULATORY_SERVICE' = "Dynamics 365 Regulatory Service - Enterprise Edition Trial" 'DYN365_RETAIL_DEVICE' = "Dynamics 365 for Retail Device" 'DYN365_RETAIL_TRIAL' = "Dynamics 365 Commerce Trial" 'DYN365_SALES_ENTERPRISE_VIRAL_TRIAL' = "Dynamics 365 Sales Enterprise vTrial" 'DYN365_SALES_INSIGHTS' = "Dynamics 365 AI for Sales (Embedded)" 'DYN365_SALES_INSIGHTS_VIRAL_TRIAL' = "Dynamics 365 Sales Insights vTrial" 'DYN365_SALES_PREMIUM' = "Dynamics 365 Sales Premium" 'DYN365_SALES_PRO' = "Dynamics 365 for Sales Professional" 'DYN365_SCM' = "Dynamics 365 for Supply Chain Management" 'DYN365_TALENT_ENTERPRISE' = "DYNAMICS 365 FOR TALENT" 'DYN365_TEAM_MEMBERS' = "Dynamics 365 Team Members" 'DYN365BC_MS_INVOICING' = "Microsoft Invoicing" 'Dynamics_365_Customer_Service_Enterprise_admin_trial' = "Dynamics 365 Customer Service Enterprise Admin" 'Dynamics_365_Customer_Service_Enterprise_viral_trial' = "Dynamics 365 Customer Service Enterprise Viral Trial" 'Dynamics_365_Field_Service_Enterprise_viral_trial' = "Dynamics 365 Field Service Viral Trial" 'Dynamics_365_for_HCM_Trial' = "Dynamics 365 for HCM Trial" 'Dynamics_365_for_Operations' = "Dynamics 365 UNF OPS Plan ENT Edition" 'Dynamics_365_for_Operations_Devices' = "Dynamics 365 Operations - Device" 'Dynamics_365_for_Operations_Sandbox_Tier2' = "Dynamics 365 for Operations non-production multi-box instance for standard acceptance testing (Tier 2)" 'Dynamics_365_for_Operations_Sandbox_Tier2_SKU' = "Dynamics 365 Operations - Sandbox Tier 2:Standard Acceptance Testing" 'Dynamics_365_for_Operations_Sandbox_Tier4' = "Dynamics 365 for Operations Enterprise Edition - Sandbox Tier 4:Standard Performance Testing" 'Dynamics_365_for_Operations_Sandbox_Tier4_SKU' = "Dynamics 365 Operations - Sandbox Tier 4:Standard Performance Testing" 'DYNAMICS_365_FOR_OPERATIONS_TEAM_MEMBERS' = "DYNAMICS 365 FOR OPERATIONS TEAM MEMBERS" 'Dynamics_365_for_OperationsDevices' = "Dynamics 365 for Operations Devices" 'Dynamics_365_for_Retail' = "DYNAMICS 365 FOR RETAIL" 'Dynamics_365_for_Retail_Team_members' = "DYNAMICS 365 FOR RETAIL TEAM MEMBERS" 'Dynamics_365_for_Talent_Team_members' = "DYNAMICS 365 FOR TALENT TEAM MEMBERS" 'Dynamics_365_Hiring_Free_PLAN' = "Dynamics 365 for Talent: Attract" 'Dynamics_365_Hiring_SKU' = "Dynamics 365 Talent: Attract" 'Dynamics_365_Onboarding_Free_PLAN' = "Dynamics 365 for Talent: Onboard" 'DYNAMICS_365_ONBOARDING_SKU' = "Dynamics 365 Talent: Onboard" 'Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox' = "Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox" 'Dynamics_365_Sales_Premium_Viral_Trial' = "Dynamics 365 Sales Premium Viral Trial" 'Dynamics_365_Talent_Onboard' = "DYNAMICS 365 FOR TALENT: ONBOARD" 'DYNB365_CSI_VIRAL_TRIAL' = "Dynamics 365 Customer Service Insights vTrial" 'E3_VDA_only' = "Windows 10/11 Enterprise E3 VDA" 'EducationAnalyticsP1' = "Education Analytics" 'EMS' = "Enterprise Mobility + Security E3" 'EMS_EDU_FACULTY' = "Enterprise Mobility + Security A3 for Faculty" 'EMS_GOV' = "Enterprise Mobility + Security G3 GCC" 'EMSPREMIUM' = "Enterprise Mobility + Security E5" 'EMSPREMIUM_GOV' = "Enterprise Mobility + Security G5 GCC" 'ENTERPRISEPACK' = "Office 365 E3" 'ENTERPRISEPACK_GOV' = "Office 365 G3 GCC" 'ENTERPRISEPACK_USGOV_DOD' = "Office 365 E3_USGOV_DOD" 'ENTERPRISEPACK_USGOV_GCCHIGH' = "Office 365 E3_USGOV_GCCHIGH" 'ENTERPRISEPACKPLUS_FACULTY' = "Office 365 A3 for faculty" 'ENTERPRISEPACKPLUS_STUDENT' = "Office 365 A3 for students" 'ENTERPRISEPREMIUM' = "Office 365 E5" 'ENTERPRISEPREMIUM_FACULTY' = "Office 365 A5 for faculty" 'ENTERPRISEPREMIUM_GOV' = "Office 365 G5 GCC" 'ENTERPRISEPREMIUM_NOPSTNCONF' = "Office 365 E5 Without Audio Conferencing" 'ENTERPRISEPREMIUM_STUDENT' = "Office 365 A5 for students" 'ENTERPRISEWITHSCAL' = "Office 365 E4" 'EOP_ENTERPRISE' = "Exchange Online Protection" 'EOP_ENTERPRISE_PREMIUM' = "Exchange Enterprise CAL Services (EOP DLP)" 'EQUIVIO_ANALYTICS' = "Office 365 Advanced Compliance" 'EQUIVIO_ANALYTICS_GOV' = "Office 365 Advanced Compliance for GCC" 'ERP_TRIAL_INSTANCE' = "Dynamics 365 Operations Trial Environment" 'EXCEL_PREMIUM' = "Microsoft Excel Advanced Analytics" 'EXCHANGE_ANALYTICS' = "Microsoft MyAnalytics (Full)" 'EXCHANGE_ANALYTICS_GOV' = "Microsoft MyAnalytics for Government (Full)" 'EXCHANGE_B_STANDARD' = "EXCHANGE ONLINE POP" 'EXCHANGE_FOUNDATION_GOV' = "EXCHANGE FOUNDATION FOR GOVERNMENT" 'EXCHANGE_L_STANDARD' = "EXCHANGE ONLINE (P1)" 'EXCHANGE_S_ARCHIVE' = "EXCHANGE ONLINE ARCHIVING FOR EXCHANGE SERVER" 'EXCHANGE_S_ARCHIVE_ADDON' = "EXCHANGE ONLINE ARCHIVING FOR EXCHANGE ONLINE" 'EXCHANGE_S_DESKLESS' = "EXCHANGE ONLINE KIOSK" 'EXCHANGE_S_DESKLESS_GOV' = "Exchange Online (Kiosk) for Government" 'EXCHANGE_S_ENTERPRISE' = "EXCHANGE ONLINE (PLAN 2)" 'EXCHANGE_S_ENTERPRISE_GOV' = "Exchange Online (Plan 2) for Government" 'EXCHANGE_S_ESSENTIALS' = "Exchange Online Essentials" 'EXCHANGE_S_FOUNDATION' = "Exchange Foundation" 'EXCHANGE_S_FOUNDATION_GOV' = "Exchange Foundation for Government" 'EXCHANGE_S_STANDARD' = "Exchange Online (Plan 1)" 'EXCHANGE_S_STANDARD_GOV' = "Exchange Online (Plan 1) for Government" 'EXCHANGE_S_STANDARD_MIDMARKET' = "EXCHANGE ONLINE PLAN" 'EXCHANGEARCHIVE' = "Exchange Online Archiving for Exchange Server" 'EXCHANGEARCHIVE_ADDON' = "Exchange Online Archiving for Exchange Online" 'EXCHANGEDESKLESS' = "Exchange Online Kiosk" 'EXCHANGEENTERPRISE' = "Exchange Online (Plan 2)" 'EXCHANGEENTERPRISE_FACULTY' = "Exchange Online (Plan 2) for Faculty" 'EXCHANGEESSENTIALS' = "Exchange Online Essentials (ExO P1 Based)" 'EXCHANGEONLINE_MULTIGEO' = "Exchange Online Multi-Geo" 'EXCHANGESTANDARD' = "Exchange Online (Plan 1)" 'EXCHANGESTANDARD_ALUMNI' = "Exchange Online (Plan 1) for Alumni with Yammer" 'EXCHANGESTANDARD_GOV' = "Exchange Online (Plan 1) for GCC" 'EXCHANGESTANDARD_STUDENT' = "Exchange Online (Plan 1) for Students" 'EXCHANGETELCO' = "Exchange Online POP" 'EXPERTS_ON_DEMAND' = "Microsoft Threat Experts - Experts on Demand" 'FLOW_BUSINESS_PROCESS' = "Power Automate per flow plan" 'FLOW_CCI_BOTS' = "Flow for CCI Bots" 'FLOW_CUSTOMER_SERVICE_PRO' = "Power Automate for Customer Service Pro" 'FLOW_DEV_VIRAL' = "Flow for Developer" 'FLOW_DYN_APPS' = "Flow for Dynamics 365" 'FLOW_DYN_P2' = "Flow for Dynamics 365" 'FLOW_DYN_TEAM' = "Power Automate for Dynamics 365" 'FLOW_FOR_PROJECT' = "Flow for Project" 'FLOW_FORMS_PRO' = "Power Automate for Dynamics 365 Customer Voice" 'FLOW_FREE' = "Microsoft Power Automate Free" 'FLOW_O365_P1' = "FLOW FOR OFFICE 365" 'FLOW_O365_P1_GOV' = "Power Automate for Office 365 for Government" 'FLOW_O365_P2' = "Power Automate for Office 365" 'FLOW_O365_P2_GOV' = "POWER AUTOMATE FOR OFFICE 365 FOR GOVERNMENT" 'FLOW_O365_P3' = "Power Automate for Office 365" 'FLOW_O365_P3_GOV' = "Power Automate for Office 365 for Government" 'FLOW_O365_S1' = "Power Automate for Office 365 F3" 'FLOW_O365_S1_GOV' = "Power Automate for Office 365 F3 for Government" 'FLOW_P1_GOV' = "Power Automate (Plan 1) for Government" 'FLOW_P2' = "Microsoft Power Automate Plan 2" 'FLOW_P2_VIRAL' = "Flow Free" 'FLOW_P2_VIRAL_REAL' = "Flow P2 Viral" 'Flow_Per_APP' = "Power Automate for Power Apps per App Plan" 'Flow_Per_APP_IWTRIAL' = "Flow per app baseline access" 'FLOW_PER_USER' = "Power Automate per user plan" 'FLOW_PER_USER_DEPT' = "Power Automate per user plan dept" 'FLOW_PER_USER_GCC' = "Power Automate per user plan for Government" 'Flow_PowerApps_PerUser' = "Power Automate for Power Apps per User Plan" 'Flow_PowerApps_PerUser_GCC' = "Power Automate for Power Apps per User Plan for GCC" 'FLOW_VIRTUAL_AGENT_BASE' = "Power Automate for Virtual Agent" 'FLOW_VIRTUAL_AGENT_USL' = "Power Automate for Virtual Agent" 'FORMS_GOV_E1' = "Forms for Government (Plan E1)" 'FORMS_GOV_E3' = "FORMS FOR GOVERNMENT (PLAN E3)" 'FORMS_GOV_E5' = "Microsoft Forms for Government (Plan E5)" 'FORMS_GOV_F1' = "Forms for Government (Plan F1)" 'FORMS_PLAN_E1' = "MICROSOFT FORMS (PLAN E1)" 'FORMS_PLAN_E3' = "Microsoft Forms (Plan E3)" 'FORMS_PLAN_E5' = "Microsoft Forms (Plan E5)" 'FORMS_PLAN_K' = "Microsoft Forms (Plan F1)" 'FORMS_PRO' = "Dynamics 365 Customer Voice Trial" 'Forms_Pro_AddOn' = "Dynamics 365 Customer Voice Additional Responses" 'Forms_Pro_CE' = "Microsoft Dynamics 365 Customer Voice for Customer Engagement Plan" 'Forms_Pro_Customer_Insights' = "Microsoft Dynamics 365 Customer Voice for Customer Insights" 'Forms_Pro_FS' = "Microsoft Dynamics 365 Customer Voice for Field Service" 'Forms_Pro_Marketing' = "Microsoft Dynamics 365 Customer Voice for Marketing" 'Forms_Pro_Marketing_App' = "Microsoft Dynamics 365 Customer Voice for Marketing Application" 'Forms_Pro_Relationship_Sales' = "Microsoft Dynamics 365 Customer Voice for Relationship Sales" 'Forms_Pro_SalesEnt' = "Microsoft Dynamics 365 Customer Voice for Sales Enterprise" 'Forms_Pro_Service' = "Microsoft Dynamics 365 Customer Voice for Customer Service Enterprise" 'Forms_Pro_USL' = "Dynamics 365 Customer Voice USL" 'GRAPH_CONNECTORS_SEARCH_INDEX' = "Graph Connectors Search with Index" 'GRAPH_CONNECTORS_SEARCH_INDEX_TOPICEXP' = "Graph Connectors Search with Index (Microsoft Viva Topics)" 'GUIDES' = "Dynamics 365 Guides" 'GUIDES_USER' = "Dynamics 365 Guides" 'IDENTITY_THREAT_PROTECTION' = "Microsoft 365 E5 Security" 'IDENTITY_THREAT_PROTECTION_FOR_EMS_E5' = "Microsoft 365 E5 Security for EMS E5" 'INFO_GOVERNANCE' = "Microsoft Information Governance" 'INFORMATION_BARRIERS' = "Information Barriers" 'INFORMATION_PROTECTION_COMPLIANCE' = "Microsoft 365 E5 Compliance" 'INSIDER_RISK' = "Microsoft Insider Risk Management" 'INSIDER_RISK_MANAGEMENT' = "Microsoft Insider Risk Management" 'Intelligent_Content_Services' = "SharePoint Syntex" 'Intelligent_Content_Services_SPO_type' = "SharePoint Syntex - SPO type" 'INTUNE_A' = "Intune" 'INTUNE_A_D' = "Microsoft Intune Device" 'INTUNE_A_D_GOV' = "Microsoft Intune Device for Government" 'Intune_AdvancedEA' = "Intune Advanced endpoint analytics" 'Intune_Defender' = "MDE_SecurityManagement" 'INTUNE_EDU' = "Intune for Education" 'INTUNE_O365' = "Mobile Device Management for Office 365" 'INTUNE_P2' = "Intune Plan 2" 'INTUNE_SMB' = "Microsoft Intune SMB" 'INTUNE_SMBIZ' = "Microsoft Intune" 'Intune-EPM' = "Intune Endpoint Privilege Management" 'Intune-MAMTunnel' = "Microsoft Tunnel for Mobile Application Management" 'IT_ACADEMY_AD' = "Microsoft Imagine Academy" 'KAIZALA_O365_P1' = "Microsoft Kaizala Pro" 'KAIZALA_O365_P2' = "Microsoft Kaizala Pro" 'KAIZALA_O365_P3' = "Microsoft Kaizala Pro" 'KAIZALA_STANDALONE' = "Microsoft Kaizala Pro" 'LITEPACK' = "Office 365 Small Business" 'LITEPACK_P2' = "Office 365 Small Business Premium" 'LOCKBOX_ENTERPRISE' = "Customer Lockbox" 'LOCKBOX_ENTERPRISE_GOV' = "Customer Lockbox for Government" 'M365_A5_SUITE_COMPONENTS_FACULTY' = "Microsoft 365 A5 Suite features for faculty" 'M365_ADVANCED_AUDITING' = "Microsoft 365 Advanced Auditing" 'M365_AUDIT_PLATFORM' = "Microsoft 365 Audit Platform" 'M365_E5_SUITE_COMPONENTS' = "Microsoft 365 E5 Suite features" 'M365_F1' = "Microsoft 365 F1" 'M365_F1_COMM' = "Microsoft 365 F1" 'M365_F1_GOV' = "Microsoft 365 F3 GCC" 'M365_G3_GOV' = "Microsoft 365 G3 GCC" 'M365_G5_GCC' = "Microsoft 365 GCC G5" 'M365_LIGHTHOUSE_CUSTOMER_PLAN1' = "Microsoft 365 Lighthouse (Plan 1)" 'M365_LIGHTHOUSE_PARTNER_PLAN1' = "Microsoft 365 Lighthouse (Plan 2)" 'M365_SECURITY_COMPLIANCE_FOR_FLW' = "Microsoft 365 Security and Compliance for Firstline Workers" 'M365EDU_A1' = "Microsoft 365 A1" 'M365EDU_A3_FACULTY' = "Microsoft 365 A3 for Faculty" 'M365EDU_A3_STUDENT' = "Microsoft 365 A3 for Students" 'M365EDU_A3_STUUSEBNFT' = "Microsoft 365 A3 for students use benefit" 'M365EDU_A3_STUUSEBNFT_RPA1' = "Microsoft 365 A3 - Unattended License for students use benefit" 'M365EDU_A5_FACULTY' = "Microsoft 365 A5 for Faculty" 'M365EDU_A5_NOPSTNCONF_STUUSEBNFT' = "Microsoft 365 A5 without Audio Conferencing for students use benefit" 'M365EDU_A5_STUDENT' = "Microsoft 365 A5 for Students" 'M365EDU_A5_STUUSEBNFT' = "Microsoft 365 A5 for students use benefit" 'MCO_TEAMS_IW' = "MICROSOFT TEAMS" 'MCO_VIRTUAL_APPT' = "Microsoft Teams Premium Virtual Appointments" 'MCOCAP' = "Microsoft Teams Shared Devices" 'MCOCAP_GOV' = "Microsoft Teams Shared Devices for GCC" 'MCOEV' = "Microsoft Teams Phone Standard" 'MCOEV_DOD' = "Microsoft Teams Phone Standard for DOD" 'MCOEV_FACULTY' = "Microsoft Teams Phone Standard for Faculty" 'MCOEV_GCCHIGH' = "Microsoft Teams Phone Standard for GCCHIGH" 'MCOEV_GOV' = "Microsoft Teams Phone Standard for GCC" 'MCOEV_STUDENT' = "Microsoft Teams Phone Standard for Students" 'MCOEV_TELSTRA' = "Microsoft Teams Phone Standard for TELSTRA" 'MCOEV_USGOV_DOD' = "Microsoft Teams Phone Standard_USGOV_DOD" 'MCOEV_USGOV_GCCHIGH' = "Microsoft Teams Phone Standard_USGOV_GCCHIGH" 'MCOEV_VIRTUALUSER' = "Microsoft 365 Phone Standard Resource Account" 'MCOEV_VIRTUALUSER_GOV' = "Microsoft 365 Phone Standard Resource Account for Government" 'MCOEVSMB' = "SKYPE FOR BUSINESS CLOUD PBX FOR SMALL AND MEDIUM BUSINESS" 'MCOEVSMB_1' = "Microsoft Teams Phone Standard for Small and Medium Business" 'MCOFREE' = "MCO FREE FOR MICROSOFT TEAMS (FREE)" 'MCOIMP' = "Skype for Business Online (Plan 1)" 'MCOIMP_GOV' = "Skype for Business Online (Plan 1) for Government" 'MCOLITE' = "SKYPE FOR BUSINESS ONLINE (PLAN P1)" 'MCOMEETACPEA' = "Microsoft 365 Audio Conferencing Pay-Per-Minute - EA" 'MCOMEETADV' = "Microsoft 365 Audio Conferencing" 'MCOMEETADV_GOV' = "Microsoft 365 Audio Conferencing for GCC" 'MCOMEETBASIC' = "Microsoft Teams Audio Conferencing with dial-out to select geographies" 'MCOPSTN_1_GOV' = "Microsoft 365 Domestic Calling Plan for GCC" 'MCOPSTN_5' = "Microsoft 365 Domestic Calling Plan (120 Minutes)" 'MCOPSTN1' = "Skype for Business PSTN Domestic Calling" 'MCOPSTN1_GOV' = "Domestic Calling for Government" 'MCOPSTN2' = "Skype for Business PSTN Domestic and International Calling" 'MCOPSTN3' = "MCOPSTN3" 'MCOPSTN5' = "Skype for Business PSTN Domestic Calling (120 Minutes)" 'MCOPSTN8' = "Microsoft 365 Domestic Calling Plan (120 min) at User Level" 'MCOPSTNC' = "Communications Credits" 'MCOPSTNEAU' = "AUSTRALIA CALLING PLAN" 'MCOPSTNEAU2' = "TELSTRA Calling for O365" 'MCOPSTNPP' = "Skype for Business PSTN Usage Calling Plan" 'MCOSTANDARD' = "Skype for Business Online (Plan 2)" 'MCOSTANDARD_GOV' = "Skype for Business Online (Plan 2) for Government" 'MCOSTANDARD_MIDMARKET' = "SKYPE FOR BUSINESS ONLINE (PLAN 2) FOR MIDSIZ" 'MCOTEAMS_ESSENTIALS' = "Teams Phone with Calling Plan" 'MCOVOICECONF' = "SKYPE FOR BUSINESS ONLINE (PLAN 3)" 'MCS_BizApps_Cloud_for_Sustainability_vTrial' = "MCS - BizApps_Cloud for Sustainability_vTrial" 'MDATP_Server' = "Microsoft Defender for Endpoint Server" 'MDATP_XPLAT' = "Microsoft Defender for Endpoint P2_XPLAT" 'MDE_LITE' = "Microsoft Defender for Endpoint Plan 1" 'MDE_SMB' = "Microsoft Defender for Business" 'MDM_SALES_COLLABORATION' = "MICROSOFT DYNAMICS MARKETING SALES COLLABORATION - ELIGIBILITY CRITERIA APPLY" 'MEE_FACULTY' = "Minecraft Education Faculty" 'MEE_STUDENT' = "Minecraft Education Student" 'MEETING_ROOM' = "Microsoft Teams Rooms Standard" 'MEETING_ROOM_NOAUDIOCONF' = "Microsoft Teams Rooms Standard without Audio Conferencing" 'MFA_PREMIUM' = "MICROSOFT AZURE MULTI-FACTOR AUTHENTICATION" 'MFA_STANDALONE' = "Microsoft Azure Multi-Factor Authentication" 'Microsoft 365 A3 Suite features for faculty' = "Microsoft 365 A3 Suite features for faculty" 'Microsoft_365_E3' = "Microsoft 365 E3 (500 seats min)_HUB" 'Microsoft_365_E3_Extra_Features' = "Microsoft 365 E3 Extra Features" 'Microsoft_365_E5' = "Microsoft 365 E5 (500 seats min)_HUB" 'Microsoft_365_E5_without_Audio_Conferencing' = "Microsoft 365 E5 without Audio Conferencing (500 seats min)_HUB" 'MICROSOFT_APPLICATION_PROTECTION_AND_GOVERNANCE_A' = "Microsoft Application Protection and Governance (A)" 'MICROSOFT_APPLICATION_PROTECTION_AND_GOVERNANCE_D' = "Microsoft Application Protection and Governance (D)" 'MICROSOFT_BUSINESS_CENTER' = "Microsoft Business Center" 'Microsoft_Cloud_App_Security_App_Governance_Add_On' = "App governance add-on to Microsoft Defender for Cloud Apps" 'Microsoft_Cloud_for_Sustainability_vTrial' = "Microsoft Cloud for Sustainability vTrial" 'MICROSOFT_COMMUNICATION_COMPLIANCE' = "Microsoft 365 Communication Compliance" 'MICROSOFT_ECDN' = "Microsoft eCDN" 'Microsoft_Intune_Suite' = "Microsoft Intune Suite" 'MICROSOFT_REMOTE_ASSIST' = "Dynamics 365 Remote Assist" 'MICROSOFT_REMOTE_ASSIST_HOLOLENS' = "Dynamics 365 Remote Assist HoloLens" 'MICROSOFT_SEARCH' = "Microsoft Search" 'Microsoft_Teams_Audio_Conferencing_select_dial_out' = "Microsoft Teams Audio Conferencing with dial-out to USA/CAN" 'Microsoft_Teams_Premium' = "Microsoft Teams Premium Introductory Pricing" 'Microsoft_Teams_Rooms_Basic' = "Microsoft Teams Rooms Basic" 'Microsoft_Teams_Rooms_Basic_FAC' = "Microsoft Teams Rooms Basic for EDU" 'Microsoft_Teams_Rooms_Basic_without_Audio_Conferencing' = "Microsoft Teams Rooms Basic without Audio Conferencing" 'Microsoft_Teams_Rooms_Pro' = "Microsoft Teams Rooms Pro" 'Microsoft_Teams_Rooms_Pro_FAC' = "Microsoft Teams Rooms Pro for EDU" 'Microsoft_Teams_Rooms_Pro_without_Audio_Conferencing' = "Microsoft Teams Rooms Pro without Audio Conferencing" 'Microsoft_Viva_Goals' = "Microsoft Viva Goals" 'Microsoft_Viva_Sales_PowerAutomate' = "Microsoft Viva Sales Premium with Power Automate" 'Microsoft_Viva_Sales_PremiumTrial' = "Microsoft Viva Sales Premium & Trial" 'Microsoft365_Lighthouse' = "Microsoft 365 Lighthouse" 'MICROSOFTBOOKINGS' = "Microsoft Bookings" 'MICROSOFTENDPOINTDLP' = "Microsoft Endpoint DLP" 'MICROSOFTSTREAM' = "MICROSOFT STREAM" 'MIDSIZEPACK' = "Office 365 Midsize Business" 'MINECRAFT_EDUCATION_EDITION' = "Minecraft Education Edition" 'MIP_S_CLP1' = "Information Protection for Office 365 - Standard" 'MIP_S_CLP2' = "Information Protection for Office 365 - Premium" 'MIP_S_Exchange' = "Data Classification in Microsoft 365" 'MIP_S_EXCHANGE_CO' = "Data Classification in Microsoft 365 - Company Level" 'ML_CLASSIFICATION' = "Microsoft ML-Based Classification" 'MMR_P1' = "Meeting Room Managed Services" 'MS_TEAMS_IW' = "Microsoft Teams Trial" 'MTP' = "Microsoft 365 Defender" 'MTR_PREM' = "Teams Rooms Premium" 'MTRProManagement' = "Microsoft Teams Rooms Pro Management" 'MYANALYTICS_P2' = "Insights by MyAnalytics" 'MYANALYTICS_P2_GOV' = "INSIGHTS BY MYANALYTICS FOR GOVERNMENT" 'NBENTERPRISE' = "Microsoft Social Engagement Enterprise" 'NBPROFESSIONALFORCRM' = "MICROSOFT SOCIAL ENGAGEMENT PROFESSIONAL - ELIGIBILITY CRITERIA APPLY" 'NONPROFIT_PORTAL' = "Nonprofit Portal" 'Nucleus' = "Nucleus" 'O365_BUSINESS' = "Microsoft 365 Apps for Business" 'O365_BUSINESS_ESSENTIALS' = "Microsoft 365 Business Basic" 'O365_BUSINESS_PREMIUM' = "Microsoft 365 Business Standard" 'O365_SB_Relationship_Management' = "OUTLOOK CUSTOMER MANAGER" 'OFFICE_BUSINESS' = "OFFICE 365 BUSINESS" 'OFFICE_FORMS_PLAN_2' = "Microsoft Forms (Plan 2)" 'OFFICE_FORMS_PLAN_3' = "Microsoft Forms (Plan 3)" 'OFFICE_PRO_PLUS_SUBSCRIPTION_SMBIZ' = "OFFICE 365 SMALL BUSINESS SUBSCRIPTION" 'OFFICE_PROPLUS_DEVICE' = "Microsoft 365 Apps for Enterprise (Device)" 'OFFICE_PROPLUS_DEVICE1' = "Microsoft 365 Apps for enterprise (device)" 'OFFICE_SHARED_COMPUTER_ACTIVATION' = "Office Shared Computer Activation" 'OFFICE365_MULTIGEO' = "Multi-Geo Capabilities in Office 365" 'OFFICEMOBILE_SUBSCRIPTION' = "OFFICEMOBILE_SUBSCRIPTION" 'OFFICEMOBILE_SUBSCRIPTION_GOV' = "Office Mobile Apps for Office 365 for GCC" 'OFFICESUBSCRIPTION' = "Microsoft 365 Apps for Enterprise" 'OFFICESUBSCRIPTION_FACULTY' = "Microsoft 365 Apps for Faculty" 'OFFICESUBSCRIPTION_GOV' = "Microsoft 365 Apps for enterprise G" 'OFFICESUBSCRIPTION_STUDENT' = "Microsoft 365 Apps for Students" 'OFFICESUBSCRIPTION_unattended' = "Microsoft 365 Apps for Enterprise (Unattended)" 'ONEDRIVE_BASIC' = "OneDrive for business Basic" 'ONEDRIVE_BASIC_GOV' = "ONEDRIVE FOR BUSINESS BASIC FOR GOVERNMENT" 'ONEDRIVE_BASIC_P2' = "OneDrive for Business (Basic 2)" 'ONEDRIVEENTERPRISE' = "ONEDRIVEENTERPRISE" 'ONEDRIVESTANDARD' = "ONEDRIVESTANDARD" 'PAM_ENTERPRISE' = "Office 365 Privileged Access Management" 'PBI_PREMIUM_P1_ADDON' = "Power BI Premium P1" 'PBI_PREMIUM_PER_USER' = "Power BI Premium Per User" 'PBI_PREMIUM_PER_USER_ADDON' = "Power BI Premium Per User Add-On" 'PBI_PREMIUM_PER_USER_DEPT' = "Power BI Premium Per User Dept" 'PBI_PREMIUM_PER_USER_FACULTY' = "Power BI Premium Per User for Faculty" 'PHONESYSTEM_VIRTUALUSER' = "Microsoft Teams Phone Resource Account" 'PHONESYSTEM_VIRTUALUSER_GOV' = "Microsoft Teams Phone Resource Account for GCC" 'POWER_APPS_DYN365_VIRAL_TRIAL' = "Power Apps for Dynamics 365 vTrial" 'POWER_AUTOMATE_ATTENDED_RPA' = "Power Automate RPA Attended" 'POWER_AUTOMATE_DYN365_VIRAL_TRIAL' = "Power Automate for Dynamics 365 vTrial" 'Power_Automate_For_Project_P1' = "POWER AUTOMATE FOR PROJECT P1" 'POWER_AUTOMATE_UNATTENDED_RPA' = "Power Automate Unattended RPA add-on" 'POWER_BI_ADDON' = "Power BI for Office 365 Add-On" 'POWER_BI_INDIVIDUAL_USER' = "Power BI" 'POWER_BI_PRO' = "Power BI Pro" 'POWER_BI_PRO_CE' = "Power BI Pro CE" 'POWER_BI_PRO_DEPT' = "Power BI Pro Dept" 'POWER_BI_PRO_FACULTY' = "Power BI Pro for Faculty" 'POWER_BI_STANDARD' = "Power BI (free)" 'POWER_BI_STANDARD_FACULTY' = "Microsoft Fabric (Free) for faculty" 'POWER_BI_STANDARD_STUDENT' = "Microsoft Fabric (Free) for student" 'Power_Pages_Internal_User' = "Power Pages Internal User" 'POWER_PAGES_VTRIAL' = "Power Pages vTrial for Makers" 'Power_Pages_vTrial_for_Makers' = "Power Pages vTrial for Makers" 'POWER_VIRTUAL_AGENTS_D365_CS_CHAT' = "Power Virtual Agents for Chat" 'POWER_VIRTUAL_AGENTS_D365_CS_MESSAGING' = "Power Virtual Agents for Digital Messaging" 'POWER_VIRTUAL_AGENTS_D365_CS_VOICE' = "Power Virtual Agents for Customer Service Voice" 'POWER_VIRTUAL_AGENTS_O365_F1' = "Power Virtual Agents for Office 365" 'POWER_VIRTUAL_AGENTS_O365_P1' = "POWER VIRTUAL AGENTS FOR OFFICE 365 P1" 'POWER_VIRTUAL_AGENTS_O365_P2' = "Power Virtual Agents for Office 365" 'POWER_VIRTUAL_AGENTS_O365_P3' = "Power Virtual Agents for Office 365" 'POWERAPPS_CUSTOMER_SERVICE_PRO' = "Power Apps for Customer Service Pro" 'POWERAPPS_DEV' = "Microsoft Power Apps for Developer" 'POWERAPPS_DEV_VIRAL' = "PowerApps for Developer" 'POWERAPPS_DYN_APPS' = "PowerApps for Dynamics 365" 'POWERAPPS_DYN_P2' = "Power Apps for Dynamics 365" 'POWERAPPS_DYN_TEAM' = "Power Apps for Dynamics 365" 'POWERAPPS_GUIDES' = "Power Apps for Guides" 'POWERAPPS_INDIVIDUAL_USER' = "Power Apps and Logic Flows" 'POWERAPPS_O365_P1' = "POWERAPPS FOR OFFICE 365" 'POWERAPPS_O365_P1_GOV' = "Power Apps for Office 365 for Government" 'POWERAPPS_O365_P2' = "Power Apps for Office 365" 'POWERAPPS_O365_P2_GOV' = "POWER APPS FOR OFFICE 365 FOR GOVERNMENT" 'POWERAPPS_O365_P3' = "Power Apps for Office 365 (Plan 3)" 'POWERAPPS_O365_P3_GOV' = "Power Apps for Office 365 for Government" 'POWERAPPS_O365_S1' = "Power Apps for Office 365 F3" 'POWERAPPS_O365_S1_GOV' = "Power Apps for Office 365 F3 for Government" 'POWERAPPS_P1_GOV' = "PowerApps Plan 1 for Government" 'POWERAPPS_P2' = "Power Apps (Plan 2)" 'POWERAPPS_P2_VIRAL' = "PowerApps Trial" 'POWERAPPS_PER_APP' = "Power Apps per app plan" 'POWERAPPS_PER_APP_IW' = "PowerApps per app baseline access" 'POWERAPPS_PER_APP_IWTRIAL' = "PowerApps per app baseline access" 'POWERAPPS_PER_APP_NEW' = "Power Apps per app plan (1 app or portal)" 'POWERAPPS_PER_USER' = "Power Apps per user plan" 'POWERAPPS_PER_USER_GCC' = "Power Apps per user plan for Government" 'POWERAPPS_PORTALS_LOGIN' = "Power Apps Portals Login Capacity Add-On" 'POWERAPPS_PORTALS_LOGIN_GCC' = "Power Apps Portals Login Capacity Add-On for Government" 'POWERAPPS_PORTALS_LOGIN_T2' = "Power Apps Portals login capacity add-on Tier 2 (10 unit min)" 'POWERAPPS_PORTALS_LOGIN_T2_GCC' = "Power Apps Portals login capacity add-on Tier 2 (10 unit min) for Government" 'POWERAPPS_PORTALS_LOGIN_T3' = "Power Apps Portals login capacity add-on Tier 3 (50 unit min)" 'POWERAPPS_PORTALS_PAGEVIEW' = "Power Apps Portals page view capacity add-on" 'POWERAPPS_PORTALS_PAGEVIEW_GCC' = "Power Apps Portals page view capacity add-on for Government" 'POWERAPPS_SALES_PRO' = "Power Apps for Sales Pro" 'POWERAPPS_VIRAL' = "Microsoft Power Apps Plan 2 Trial" 'POWERAPPSFREE' = "MICROSOFT POWERAPPS" 'POWERAUTOMATE_ATTENDED_RPA' = "Power Automate per user with attended RPA plan" 'POWERAUTOMATE_DESKTOP_FOR_WIN' = "PAD for Windows" 'POWERAUTOMATE_UNATTENDED_RPA' = "Power Automate unattended RPA add-on" 'POWERBI_PRO_GOV' = "Power BI Pro for GCC" 'POWERFLOW_P2' = "Microsoft Power Apps Plan 2 (Qualified Offer)" 'POWERFLOWSFREE' = "LOGIC FLOWS" 'POWERVIDEOSFREE' = "MICROSOFT POWER VIDEOS BASIC" 'PREMIUM_ENCRYPTION' = "Premium Encryption in Office 365" 'PRIVACY_MANAGEMENT_RISK' = "Privacy Management � risk" 'PRIVACY_MANAGEMENT_RISK_EDU' = "Privacy Management - risk for EDU" 'PRIVACY_MANAGEMENT_RISK_GCC' = "Privacy Management - risk GCC" 'PRIVACY_MANAGEMENT_RISK_USGOV_DOD' = "Privacy Management - risk_USGOV_DOD" 'PRIVACY_MANAGEMENT_RISK_USGOV_GCCHIGH' = "Privacy Management - risk_USGOV_GCCHIGH" 'PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_1_EDU_V2' = "Privacy Management - subject rights request (1) for EDU" 'PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_1_V2' = "Privacy Management - subject rights request (1)" 'PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_1_V2_GCC' = "Privacy Management - subject rights request (1) GCC" 'PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_1_V2_USGOV_DOD' = "Privacy Management - subject rights request (1) USGOV_DOD" 'PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_1_V2_USGOV_GCCHIGH' = "Privacy Management - subject rights request (1) USGOV_GCCHIGH" 'PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_10_EDU_V2' = "Privacy Management - subject rights request (10) for EDU" 'PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_10_V2' = "Privacy Management - subject rights request (10)" 'PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_10_V2_GCC' = "Privacy Management - subject rights request (10) GCC" 'PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_10_V2_USGOV_DOD' = "Privacy Management - subject rights request (10) USGOV_DOD" 'PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_10_V2_USGOV_GCCHIGH' = "Privacy Management - subject rights request (10) USGOV_GCCHIGH" 'PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_100_EDU_V2' = "Privacy Management - subject rights request (100) for EDU" 'PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_100_V2' = "Privacy Management - subject rights request (100)" 'PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_100_V2_GCC' = "Privacy Management - subject rights request (100) GCC" 'PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_100_V2_USGOV_DOD' = "Privacy Management - subject rights request (100) USGOV_DOD" 'PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_100_V2_USGOV_GCCHIGH' = "Privacy Management - subject rights request (100) USGOV_GCCHIGH" 'PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_50' = "Privacy Management - subject rights request (50)" 'PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_50_EDU_V2' = "Privacy Management - subject rights request (50) for EDU" 'PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_50_V2' = "Privacy Management - subject rights request (50)" 'PRIVACY_MANGEMENT_DSR' = "Privacy Management - Subject Rights Request" 'PRIVACY_MANGEMENT_DSR_1' = "Privacy Management - Subject Rights Request (1 - Exchange)" 'PRIVACY_MANGEMENT_DSR_10' = "Privacy Management - Subject Rights Request (10)" 'PRIVACY_MANGEMENT_DSR_100' = "Privacy Management - Subject Rights Request (100)" 'PRIVACY_MANGEMENT_DSR_EXCHANGE' = "Privacy Management - Subject Rights Request (Exchange)" 'PRIVACY_MANGEMENT_DSR_EXCHANGE_1' = "Privacy Management - Subject Rights Request (1)" 'PRIVACY_MANGEMENT_DSR_EXCHANGE_10' = "Privacy Management - Subject Rights Request (10 - Exchange)" 'PRIVACY_MANGEMENT_DSR_EXCHANGE_100' = "Privacy Management - Subject Rights Request (100 - Exchange)" 'PRIVACY_MANGEMENT_RISK' = "Priva - Risk" 'PRIVACY_MANGEMENT_RISK_EXCHANGE' = "Priva - Risk (Exchange)" 'PROJECT_CLIENT_SUBSCRIPTION' = "Project Online Desktop Client" 'PROJECT_CLIENT_SUBSCRIPTION_GOV' = "Project Online Desktop Client for Government" 'PROJECT_ESSENTIALS' = "Project Online Essentials" 'PROJECT_ESSENTIALS_GOV' = "Project Online Essentials for Government" 'PROJECT_FOR_PROJECT_OPERATIONS' = "Project for Project Operations" 'PROJECT_MADEIRA_PREVIEW_IW' = "Dynamics 365 Business Central for IWs" 'PROJECT_MADEIRA_PREVIEW_IW_SKU' = "Dynamics 365 Business Central for IWs" 'PROJECT_O365_F3' = "Project for Office (Plan F)" 'PROJECT_O365_P1' = "Project for Office (Plan E1)" 'PROJECT_O365_P2' = "Project for Office (Plan E3)" 'PROJECT_O365_P3' = "Project for Office (Plan E5)" 'PROJECT_P1' = "Project Plan 1" 'PROJECT_PLAN1_DEPT' = "Project Plan 1 (for Department)" 'PROJECT_PLAN3_DEPT' = "Project Plan 3 (for Department)" 'PROJECT_PROFESSIONAL' = "Project P3" 'PROJECT_PROFESSIONAL_FACULTY' = "Project P3 for Faculty" 'PROJECTCLIENT' = "Project for Office 365" 'PROJECTESSENTIALS' = "Project Online Essentials" 'PROJECTESSENTIALS_FACULTY' = "Project Online Essentials for Faculty" 'PROJECTESSENTIALS_GOV' = "Project Online Essentials for GCC" 'PROJECTONLINE_PLAN_1' = "Project Online Premium Without Project Client" 'PROJECTONLINE_PLAN_1_FACULTY' = "Project Plan 5 without Project Client for Faculty" 'PROJECTONLINE_PLAN_2' = "Project Online With Project for Office 365" 'PROJECTPREMIUM' = "Project Online Premium" 'PROJECTPREMIUM_GOV' = "Project Plan 5 for GCC" 'PROJECTPROFESSIONAL' = "Project Plan 3" 'PROJECTPROFESSIONAL_FACULTY' = "Project Plan 3 for Faculty" 'PROJECTPROFESSIONAL_GOV' = "Project Plan 3 for GCC" 'PROJECTWORKMANAGEMENT' = "Microsoft Planner" 'PROJECTWORKMANAGEMENT_GOV' = "Office 365 Planner for Government" 'RECORDS_MANAGEMENT' = "Microsoft Records Management" 'REMOTE_HELP' = "Remote help" 'RIGHTSMANAGEMENT' = "Azure Information Protection Plan 1" 'RIGHTSMANAGEMENT_ADHOC' = "Rights Management Adhoc" 'RMS_S_ADHOC' = "Rights Management Adhoc" 'RMS_S_BASIC' = "Microsoft Azure Rights Management Service" 'RMS_S_ENTERPRISE' = "AZURE INFORMATION PROTECTION PREMIUM P1" 'RMS_S_ENTERPRISE)' = "Microsoft Azure Active Directory Rights" 'RMS_S_ENTERPRISE_GOV' = "Azure Rights Management" 'RMS_S_PREMIUM' = "MICROSOFT AZURE ACTIVE DIRECTORY RIGHTS" 'RMS_S_PREMIUM_GOV' = "Azure Information Protection Premium P1 for GCC" 'RMS_S_PREMIUM2' = "AZURE INFORMATION PROTECTION PREMIUM P2" 'RMS_S_PREMIUM2_GOV' = "Azure Information Protection Premium P2 for GCC" 'RMSBASIC' = "Rights Management Service Basic Content Protection" 'SAFEDOCS' = "Office 365 SafeDocs" 'SCHOOL_DATA_SYNC_P1' = "School Data Sync (Plan 1)" 'SCHOOL_DATA_SYNC_P2' = "School Data Sync (Plan 2)" 'SharePoint Plan 1G' = "SharePoint Plan 1G" 'SHAREPOINT_PROJECT' = "Project Online Service" 'SHAREPOINT_PROJECT_EDU' = "Project Online Service for Education" 'SHAREPOINT_PROJECT_GOV' = "Project Online Service for Government" 'SHAREPOINT_S_DEVELOPER' = "SHAREPOINT FOR DEVELOPER" 'SHAREPOINTDESKLESS' = "SharePoint Online Kiosk" 'SHAREPOINTDESKLESS_GOV' = "SharePoint KioskG" 'SHAREPOINTENTERPRISE' = "SharePoint Online (Plan 2)" 'SHAREPOINTENTERPRISE_EDU' = "SharePoint (Plan 2) for Education" 'SHAREPOINTENTERPRISE_GOV' = "SharePoint Plan 2G" 'SHAREPOINTENTERPRISE_MIDMARKET' = "SHAREPOINT PLAN 1" 'SHAREPOINTLITE' = "SHAREPOINTLITE" 'SHAREPOINTONLINE_MULTIGEO' = "SharePoint Multi-Geo" 'SHAREPOINTSTANDARD' = "SharePoint Online (Plan 1)" 'SHAREPOINTSTANDARD_EDU' = "SharePoint (Plan 1) for Education" 'SHAREPOINTSTORAGE' = "Office 365 Extra File Storage" 'SHAREPOINTSTORAGE_GOV' = "Office 365 Extra File Storage for GCC" 'SHAREPOINTWAC' = "Office for the web" 'SHAREPOINTWAC_DEVELOPER' = "OFFICE ONLINE FOR DEVELOPER" 'SHAREPOINTWAC_EDU' = "Office for the Web for Education" 'SHAREPOINTWAC_GOV' = "Office for the Web for Government" 'SKU_Dynamics_365_for_HCM_Trial' = "Dynamics 365 for Talent" 'SMB_APPS' = "Business Apps (free)" 'SMB_BUSINESS' = "Microsoft 365 Apps for Business" 'SMB_BUSINESS_ESSENTIALS' = "Microsoft 365 Business Basic" 'SMB_BUSINESS_PREMIUM' = "Microsoft 365 Business Standard - Prepaid Legacy" 'SOCIAL_ENGAGEMENT_APP_USER' = "Dynamics 365 AI for Market Insights (Preview)" 'SPB' = "Microsoft 365 Business Premium" 'SPE_E3' = "Microsoft 365 E3" 'SPE_E3_RPA1' = "Microsoft 365 E3 - Unattended License" 'SPE_E3_USGOV_DOD' = "Microsoft 365 E3_USGOV_DOD" 'SPE_E3_USGOV_GCCHIGH' = "Microsoft 365 E3_USGOV_GCCHIGH" 'SPE_E5' = "Microsoft 365 E5" 'SPE_E5_CALLINGMINUTES' = "Microsoft 365 E5 with Calling Minutes" 'SPE_E5_NOPSTNCONF' = "Microsoft 365 E5 without Audio Conferencing" 'SPE_F1' = "Microsoft 365 F3" 'SPE_F5_COMP' = "Microsoft 365 F5 Compliance Add-on" 'SPE_F5_COMP_AR_D_USGOV_DOD' = "Microsoft 365 F5 Compliance Add-on AR (DOD)_USGOV_DOD" 'SPE_F5_COMP_AR_USGOV_GCCHIGH' = "Microsoft 365 F5 Compliance Add-on AR_USGOV_GCCHIGH" 'SPE_F5_COMP_GCC' = "Microsoft 365 F5 Compliance Add-on GCC" 'SPE_F5_SEC' = "Microsoft 365 F5 Security Add-on" 'SPE_F5_SECCOMP' = "Microsoft 365 F5 Security + Compliance Add-on" 'SPZA' = "APP CONNECT" 'SPZA_IW' = "App Connect IW" 'SQL_IS_SSIM' = "Microsoft Power BI Information Services Plan 1" 'STANDARDPACK' = "Office 365 E1" 'STANDARDPACK_GOV' = "Office 365 G1 GCC" 'STANDARDWOFFPACK' = "Office 365 E2" 'STANDARDWOFFPACK_FACULTY' = "Office 365 A1 for faculty" 'STANDARDWOFFPACK_IW_FACULTY' = "Office 365 A1 Plus for faculty" 'STANDARDWOFFPACK_IW_STUDENT' = "Office 365 A1 Plus for students" 'STANDARDWOFFPACK_STUDENT' = "Office 365 A1 for students" 'STREAM' = "Microsoft Stream" 'STREAM_O365_E1' = "Microsoft Stream for Office 365 E1" 'STREAM_O365_E1_GOV' = "Microsoft Stream for O365 for Government (E1)" 'STREAM_O365_E3' = "Microsoft Stream for Office 365 E3" 'STREAM_O365_E3_GOV' = "MICROSOFT STREAM FOR O365 FOR GOVERNMENT (E3)" 'STREAM_O365_E5' = "Microsoft Stream for Office 365 E5" 'STREAM_O365_E5_GOV' = "Stream for Office 365 for Government (E5)" 'STREAM_O365_K' = "Microsoft Stream for O365 K SKU" 'STREAM_O365_K_GOV' = "Microsoft Stream for O365 for Government (F1)" 'STREAM_O365_SMB' = "Stream for Office 365" 'STREAM_P2' = "Microsoft Stream Plan 2" 'STREAM_STORAGE' = "Microsoft Stream Storage Add-On (500 GB)" 'SWAY' = "Sway" 'TEAMS_ADVCOMMS' = "Microsoft 365 Advanced Communications" 'TEAMS_AR_DOD' = "Microsoft Teams for DOD (AR)" 'TEAMS_AR_GCCHIGH' = "Microsoft Teams for GCCHigh (AR)" 'TEAMS_COMMERCIAL_TRIAL' = "Microsoft Teams Commercial Cloud" 'Teams_Ess' = "Microsoft Teams Essentials" 'TEAMS_ESSENTIALS_AAD' = "Microsoft Teams Essentials (AAD Identity)" 'TEAMS_EXPLORATORY' = "Microsoft Teams Exploratory" 'TEAMS_FREE' = "Microsoft Teams (Free)" 'TEAMS_FREE_SERVICE' = "TEAMS FREE SERVICE" 'TEAMS_GOV' = "Microsoft Teams for Government" 'Teams_Room_Basic' = "Teams Room Basic" 'Teams_Room_Pro' = "Teams Room Pro" 'Teams_Room_Standard' = "Teams Room Standard" 'TEAMS1' = "Microsoft Teams" 'TeamsEss' = "Microsoft Teams Essentials" 'TEAMSMULTIGEO' = "Teams Multi-Geo" 'TEAMSPRO_CUST' = "Microsoft Teams Premium Personalized" 'TEAMSPRO_MGMT' = "Microsoft Teams Premium Intelligent" 'TEAMSPRO_PROTECTION' = "Microsoft Teams Premium Secure" 'TEAMSPRO_VIRTUALAPPT' = "Microsoft Teams Premium Virtual Appointment" 'TEAMSPRO_WEBINAR' = "Microsoft Teams Premium Webinar" 'THREAT_INTELLIGENCE' = "Microsoft Defender for Office 365 (Plan 2)" 'THREAT_INTELLIGENCE_APP' = "Defender Threat Intelligence" 'THREAT_INTELLIGENCE_GOV' = "Microsoft Defender for Office 365 (Plan 2) GCC" 'TOPIC_EXPERIENCES' = "Viva Topics" 'TVM_PREMIUM_1' = "Microsoft Defender Vulnerability Management" 'TVM_Premium_Add_on' = "Microsoft Defender Vulnerability Management Add-on" 'TVM_Premium_Standalone' = "Microsoft Defender Vulnerability Management" 'UNIVERSAL_PRINT' = "Universal Print" 'UNIVERSAL_PRINT_01' = "Universal Print" 'UNIVERSAL_PRINT_NO_SEEDING' = "Universal Print Without Seeding" 'VIRTUAL_AGENT_BASE' = "Power Virtual Agent" 'VIRTUAL_AGENT_USL' = "Power Virtual Agent User License" 'Virtualization Rights for Windows 10 (E3/E5+VDA)' = "Windows 10 Enterprise (New)" 'Virtualization Rights for Windows 10' = "Windows 10/11 Enterprise" 'Virtualization Rights for Windows 10 (E3/E5+VDA)' = "Windows 10/11 Enterprise" 'VISIO_CLIENT_SUBSCRIPTION' = "Visio Desktop App" 'VISIO_CLIENT_SUBSCRIPTION_GOV' = "VISIO DESKTOP APP FOR Government" 'VISIO_PLAN1_DEPT' = "Visio Plan 1" 'VISIO_PLAN2_DEPT' = "Visio Plan 2" 'VISIOCLIENT' = "Visio Online Plan 2" 'VISIOCLIENT_FACULTY' = "Visio Plan 2 for Faculty" 'VISIOCLIENT_GOV' = "Visio Plan 2 for GCC" 'VISIOONLINE' = "Visio web app" 'VISIOONLINE_GOV' = "VISIO WEB APP FOR GOVERNMENT" 'VISIOONLINE_PLAN1' = "Visio Online Plan 1" 'VIVA' = "Microsoft Viva Suite" 'Viva_Goals_Premium' = "Viva Goals" 'VIVA_LEARNING_PREMIUM' = "Viva Learning" 'VIVA_LEARNING_SEEDED' = "Viva Learning Seeded" 'VIVAENGAGE_COMMUNITIES_AND_COMMUNICATIONS' = "Viva Engage Communities and Communications" 'VIVAENGAGE_CORE' = "Viva Engage Core" 'VIVAENGAGE_KNOWLEDGE' = "Viva Engage Knowledge" 'WACONEDRIVEENTERPRISE' = "OneDrive for Business (Plan 2)" 'WACONEDRIVESTANDARD' = "OneDrive for Business (Plan 1)" 'WHITEBOARD_FIRSTLINE1' = "Whiteboard (Firstline)" 'WHITEBOARD_PLAN1' = "Whiteboard (Plan 1)" 'WHITEBOARD_PLAN2' = "Whiteboard (Plan 2)" 'WHITEBOARD_PLAN3' = "Whiteboard (Plan 3)" 'WIN_DEF_ATP' = "Microsoft Defender for Endpoint" 'WIN_ENT_E5' = "Windows 10/11 Enterprise E5 (Original)" 'WIN10_ENT_A3_FAC' = "Windows 10/11 Enterprise A3 for faculty" 'WIN10_ENT_A3_STU' = "Windows 10/11 Enterprise A3 for students" 'WIN10_ENT_A5_FAC' = "Windows 10/11 Enterprise A5 for faculty" 'WIN10_ENT_LOC_F1' = "Windows 10 Enterprise E3 (Local Only)" 'WIN10_PRO_ENT_SUB' = "Windows 10/11 Enterprise E3" 'WIN10_VDA_E3' = "Windows 10/11 Enterprise E3" 'WIN10_VDA_E5' = "Windows 10/11 Enterprise E5" 'WINBIZ' = "Windows 10/11 Business" 'WINDEFATP' = "Microsoft Defender for Endpoint" 'Windows Autopatch' = "Windows Autopatch" 'Windows Store for Business EDU Store_faculty' = "Windows Store for Business EDU Store_faculty" 'Windows_365_S_2vCPU_4GB_128GB' = "Windows 365 Shared Use 2 vCPU 4 GB 128 GB" 'Windows_365_S_2vCPU_4GB_256GB' = "Windows 365 Shared Use 2 vCPU 4 GB 256 GB" 'Windows_365_S_2vCPU_4GB_64GB' = "Windows 365 Shared Use 2 vCPU 4 GB 64 GB" 'Windows_365_S_2vCPU_8GB_128GB' = "Windows 365 Shared Use 2 vCPU 8 GB 128 GB" 'Windows_365_S_2vCPU_8GB_256GB' = "Windows 365 Shared Use 2 vCPU 8 GB 256 GB" 'Windows_365_S_4vCPU_16GB_128GB' = "Windows 365 Shared Use 4 vCPU 16 GB 128 GB" 'Windows_365_S_4vCPU_16GB_256GB' = "Windows 365 Shared Use 4 vCPU 16 GB 256 GB" 'Windows_365_S_4vCPU_16GB_512GB' = "Windows 365 Shared Use 4 vCPU 16 GB 512 GB" 'Windows_365_S_8vCPU_32GB_128GB' = "Windows 365 Shared Use 8 vCPU 32 GB 128 GB" 'Windows_365_S_8vCPU_32GB_256GB' = "Windows 365 Shared Use 8 vCPU 32 GB 256 GB" 'Windows_365_S_8vCPU_32GB_512GB' = "Windows 365 Shared Use 8 vCPU 32 GB 512 GB" 'Windows_Autopatch' = "Windows Autopatch" 'WINDOWS_STORE' = "Windows Store for Business" 'WINDOWSUPDATEFORBUSINESS_DEPLOYMENTSERVICE' = "Windows Update for Business Deployment Service" 'WINE5_GCC_COMPAT' = "Windows 10/11 Enterprise E5 Commercial (GCC Compatible)" 'WORKPLACE_ANALYTICS' = "Microsoft Workplace Analytics" 'WORKPLACE_ANALYTICS_INSIGHTS_BACKEND' = "Microsoft Viva Insights Backend" 'WORKPLACE_ANALYTICS_INSIGHTS_USER' = "Microsoft Viva Insights" 'WSFB_EDU_FACULTY' = "Windows Store for Business EDU Faculty" 'YAMMER_EDU' = "Yammer for Academic" 'YAMMER_ENTERPRISE' = "YAMMER_ENTERPRISE" 'YAMMER_MIDSIZE' = "YAMMER MIDSIZE" } $SKUO365 = [ordered] @{ 'AAD_PREMIUM' = "AAD_PREMIUM" 'ADALLOM_S_DISCOVERY' = "ADALLOM_S_DISCOVERY" 'ADALLOM_S_O365' = "ADALLOM_S_O365" 'Advanced Communications' = "ADV_COMMS" 'AI Builder Capacity add-on' = "CDSAICAPACITY" 'AI Builder capacity Per App add-on' = "CDSAICAPACITY_PERAPP" 'AI Builder capacity Per User add-on' = "CDSAICAPACITY_PERUSER" 'APP CONNECT' = "SPZA" 'App Connect IW' = "SPZA_IW" 'App governance add-on to Microsoft Defender for Cloud Apps' = "Microsoft_Cloud_App_Security_App_Governance_Add_On" 'Asset Maintenance Add-in' = "D365_AssetforSCM" 'ATP_ENTERPRISE_GOV' = "ATP_ENTERPRISE_GOV" 'AUSTRALIA CALLING PLAN' = "MCOPSTNEAU" 'Azure Active Directory' = "AAD_SMB" 'Azure Active Directory Basic' = "AAD_BASIC" 'Azure Active Directory Basic for EDU' = "AAD_BASIC_EDU" 'Azure Active Directory Basic for Education' = "AAD_BASIC_EDU" 'Azure Active Directory for Education' = "AAD_EDU" 'Azure Active Directory Premium P1' = "AAD_PREMIUM" 'Azure Active Directory Premium P1 for Faculty' = "AAD_PREMIUM_FACULTY" 'Azure Active Directory Premium P2' = "AAD_PREMIUM_P2" 'Azure Active Directory Premium Plan 1' = "AAD_PREMIUM" 'Azure Information Protection Plan 1' = "RIGHTSMANAGEMENT" 'Azure Information Protection Premium P' = "RMS_S_PREMIUM" 'AZURE INFORMATION PROTECTION PREMIUM P1' = "RMS_S_ENTERPRISE" 'Azure Information Protection Premium P1 for GCC' = "RMS_S_PREMIUM_GOV" 'AZURE INFORMATION PROTECTION PREMIUM P2' = "RMS_S_PREMIUM2" 'Azure Information Protection Premium P2 for GCC' = "RMS_S_PREMIUM2_GOV" 'Azure Rights Management' = "RMS_S_ENTERPRISE" 'AZURE RIGHTS MANAGEMENT PREMIUM FOR GOVERNMENT' = "RMS_S_PREMIUM_GOV" 'BI_AZURE_P_2_GOV' = "BI_AZURE_P_2_GOV" 'BI_AZURE_P0' = "BI_AZURE_P0" 'BPOS_S_TODO_1' = "BPOS_S_TODO_1" 'BPOS_S_TODO_2' = "BPOS_S_TODO_2" 'BPOS_S_TODO_3' = "BPOS_S_TODO_3" 'Business Apps (free)' = "SMB_APPS" 'CDS Per app baseline access' = "CDS_PER_APP_IWTRIAL" 'CDS PowerApps per app plan' = "CDS_PER_APP" 'CDS PowerApps Portals page view capacity add-on' = "CDS_POWERAPPS_PORTALS_PAGEVIEW" 'CDS PowerApps Portals page view capacity add-on for GCC' = "CDS_POWERAPPS_PORTALS_PAGEVIEW_GCC" 'CDS_O365_P3_GCC' = "CDS_O365_P3_GCC" 'CLOUD APP SECURITY DISCOVERY' = "ADALLOM_S_DISCOVERY" 'Common Data Service' = "DYN365_CDS_FORMS_PRO" 'Common Data Service - DEV VIRAL' = "DYN365_CDS_DEV_VIRAL" 'Common Data Service - O365 F1' = "DYN365_CDS_O365_F1_GCC" 'Common Data Service - O365 P1' = "DYN365_CDS_O365_P1" 'Common Data Service - O365 P1 GCC' = "DYN365_CDS_O365_P1_GCC" 'Common Data Service - O365 P2' = "DYN365_CDS_O365_P2" 'COMMON DATA SERVICE - O365 P2 GCC' = "DYN365_CDS_O365_P2_GCC" 'Common Data Service - O365 P3' = "DYN365_CDS_O365_P3" 'Common Data Service - P2' = "DYN365_CDS_P2" 'Common Data Service - VIRAL' = "DYN365_CDS_VIRAL" 'Common Data Service Attended RPA' = "CDS_ATTENDED_RPA" 'Common Data Service Database Capacity' = "CDS_DB_CAPACITY" 'Common Data Service Database Capacity for Government' = "CDS_DB_CAPACITY_GOV" 'Common Data Service for Apps Database Capacity' = "CDS_DB_CAPACITY" 'Common Data Service for Apps Database Capacity for Government' = "CDS_DB_CAPACITY_GOV" 'Common Data Service for Apps File Capacity' = "CDS_FILE_CAPACITY" 'Common Data Service for Apps Log Capacity' = "CDS_LOG_CAPACITY" 'Common Data Service for CCI Bots' = "DYN365_CDS_CCI_BOTS" 'Common Data Service for Customer Insights' = "CDS_CUSTOMER_INSIGHTS" 'Common Data Service for Customer Insights Trial' = "CDS_CUSTOMER_INSIGHTS_TRIAL" 'Common Data Service for Dynamics 365 Finance' = "DYN365_CDS_FINANCE" 'COMMON DATA SERVICE FOR DYNAMICS 365 SUPPLY CHAIN MANAGEMENT' = "DYN365_CDS_SUPPLYCHAINMANAGEMENT" 'Common data service for Flow per business process plan' = "CDS_Flow_Business_Process" 'Common Data Service for Government' = "DYN365_CDS_P2_GOV" 'Common Data Service for Project' = "DYN365_CDS_PROJECT" 'COMMON DATA SERVICE FOR PROJECT P1' = "DYN365_CDS_FOR_PROJECT_P1" 'Common Data Service for Remote Assist' = "CDS_REMOTE_ASSIST" 'Common Data Service for SharePoint Syntex' = "CDS_O365_E5_KM" 'Common Data Service for Teams' = "CDS_O365_P2" 'Common Data Service for Teams_F1' = "CDS_O365_F1" 'Common Data Service for Teams_F1 GCC' = "CDS_O365_F1_GCC" 'COMMON DATA SERVICE FOR TEAMS_P1' = "CDS_O365_P1" 'Common Data Service for Teams_P1 GCC' = "CDS_O365_P1_GCC" 'Common Data Service for Teams_P2' = "CDS_O365_P2" 'COMMON DATA SERVICE FOR TEAMS_P2 GCC' = "CDS_O365_P2_GCC" 'Common Data Service for Teams_P3' = "CDS_O365_P3" 'Common Data Service for Virtual Agent Base' = "CDS_VIRTUAL_AGENT_BASE" 'Common Data Service Log Capacity' = "CDS_LOG_CAPACITY" 'Common Data Service Power Apps Portals Login Capacity' = "CDS_POWERAPPS_PORTALS_LOGIN" 'Common Data Service Power Apps Portals Login Capacity for GCC' = "CDS_POWERAPPS_PORTALS_LOGIN_GCC" 'Common Data Service Unattended RPA' = "CDS_UNATTENDED_RPA" 'Communications Credits' = "MCOPSTNC" 'COMMUNICATIONS_DLP' = "COMMUNICATIONS_DLP" 'Compliance Manager Premium Assessment Add-On' = "CMPA_addon" 'Compliance Manager Premium Assessment Add-On for GCC' = "CMPA_addon_GCC" 'Content_Explorer' = "Content_Explorer" 'ContentExplorer_Standard' = "ContentExplorer_Standard" 'CRM Hybrid Connector' = "CRM_HYBRIDCONNECTOR" 'Customer Lockbox' = "LOCKBOX_ENTERPRISE" 'Customer Lockbox for Government' = "LOCKBOX_ENTERPRISE_GOV" 'Customer Voice for Dynamics 365 vTrial' = "CUSTOMER_VOICE_DYN365_VIRAL_TRIAL" 'CUSTOMER_KEY' = "CUSTOMER_KEY" 'Data Classification in Microsoft 365' = "MIP_S_Exchange" 'Data Classification in Microsoft 365 - Company Level' = "MIP_S_EXCHANGE_CO" 'Data Loss Prevention' = "BPOS_S_DlpAddOn" 'Dataverse for Cust Insights�BASE' = "CDS_CUSTOMER_INSIGHTS_BASE" 'Dataverse for Customer Insights�BASE' = "CDS_CUSTOMER_INSIGHTS_BASE" 'Dataverse for PAD' = "DATAVERSE_FOR_POWERAUTOMATE_DESKTOP" 'Dataverse for Power Apps per app' = "DATAVERSE_POWERAPPS_PER_APP_NEW" 'Defender Threat Intelligence' = "Defender_Threat_Intelligence" 'DOMESTIC AND INTERNATIONAL CALLING PLAN' = "MCOPSTN2" 'Domestic Calling for Government' = "MCOPSTN1_GOV" 'DOMESTIC CALLING PLAN' = "MCOPSTN1" 'DYN365_CDS_O365_F1' = "DYN365_CDS_O365_F1" 'DYN365_CDS_O365_P3_GCC' = "DYN365_CDS_O365_P3_GCC" 'Dynamics 365 - Additional Database Storage (Qualified Offer)' = "CRMSTORAGE" 'Dynamics 365 - Additional Non-Production Instance (Qualified Offer)' = "CRMTESTINSTANCE" 'Dynamics 365 - Additional Production Instance (Qualified Offer)' = "CRMINSTANCE" 'Dynamics 365 AI for Customer Service Trial' = "DYN365_AI_SERVICE_INSIGHTS" 'Dynamics 365 AI for Customer Service Virtual Agents Viral' = "CCIBOTS_PRIVPREV_VIRAL" 'Dynamics 365 AI for Market Insights - Free' = "SOCIAL_ENGAGEMENT_APP_USER" 'Dynamics 365 AI for Market Insights (Preview)' = "SOCIAL_ENGAGEMENT_APP_USER" 'Dynamics 365 AI for Sales (Embedded)' = "DYN365_SALES_INSIGHTS" 'Dynamics 365 Asset Management Addl Assets' = "DYN365_ASSETMANAGEMENT" 'Dynamics 365 Business Central Additional Environment Addon' = "DYN365_BUSCENTRAL_ADD_ENV_ADDON" 'Dynamics 365 Business Central Database Capacity' = "DYN365_BUSCENTRAL_DB_CAPACITY" 'Dynamics 365 Business Central Essentials' = "DYN365_BUSCENTRAL_ESSENTIAL" 'Dynamics 365 Business Central External Accountant' = "DYN365_FINANCIALS_ACCOUNTANT_SKU" 'Dynamics 365 Business Central for IWs' = "PROJECT_MADEIRA_PREVIEW_IW_SKU" 'Dynamics 365 Business Central Premium' = "DYN365_BUSCENTRAL_PREMIUM" 'Dynamics 365 Business Central Team Members' = "DYN365_BUSCENTRAL_TEAM_MEMBER" 'Dynamics 365 Commerce Trial' = "DYN365_RETAIL_TRIAL" 'Dynamics 365 Customer Engagement Plan' = "DYN365_ENTERPRISE_PLAN1" 'Dynamics 365 Customer Insights' = "DYN365_CUSTOMER_INSIGHTS_BASE" 'Dynamics 365 Customer Insights Attach' = "DYN365_CUSTOMER_INSIGHTS_ATTACH" 'Dynamics 365 Customer Insights Engagement Insights' = "DYN365_CUSTOMER_INSIGHTS_ENGAGEMENT_INSIGHTS_BASE" 'Dynamics 365 Customer Insights Engagement Insights Viral' = "DYN365_CUSTOMER_INSIGHTS_ENGAGEMENT_INSIGHTS_BASE_TRIAL" 'Dynamics 365 Customer Insights Standalone' = "DYN365_CUSTOMER_INSIGHTS_BASE" 'Dynamics 365 Customer Insights Viral Plan' = "DYN365_CUSTOMER_INSIGHTS_VIRAL" 'Dynamics 365 Customer Insights vTrial' = "DYN365_CUSTOMER_INSIGHTS_VIRAL" 'Dynamics 365 Customer Service Chat Application Integration' = "DYN365_CS_CHAT_FPA" 'Dynamics 365 Customer Service Digital Messaging add-on' = "DYN365_CS_MESSAGING_TPS" 'Dynamics 365 Customer Service Digital Messaging vTrial' = "DYN365_CS_MESSAGING_VIRAL_TRIAL" 'Dynamics 365 Customer Service Enterprise Admin' = "Dynamics_365_Customer_Service_Enterprise_admin_trial" 'Dynamics 365 Customer Service Enterprise Viral Trial' = "Dynamics_365_Customer_Service_Enterprise_viral_trial" 'Dynamics 365 Customer Service Enterprise vTrial' = "DYN365_CS_ENTERPRISE_VIRAL_TRIAL" 'Dynamics 365 Customer Service Insights for CE Plan' = "D365_CSI_EMBED_CE" 'Dynamics 365 Customer Service Insights for CS Enterprise' = "D365_CSI_EMBED_CSEnterprise" 'Dynamics 365 Customer Service Insights Trial' = "DYN365_AI_SERVICE_INSIGHTS" 'Dynamics 365 Customer Service Insights vTrial' = "DYNB365_CSI_VIRAL_TRIAL" 'Dynamics 365 Customer Service Professional' = "DYN365_CUSTOMER_SERVICE_PRO" 'Dynamics 365 Customer Service Voice vTrial' = "DYN365_CS_VOICE_VIRAL_TRIAL" 'Dynamics 365 Customer Voice' = "DYN365_CUSTOMER_VOICE_BASE" 'Dynamics 365 Customer Voice Additional Responses' = "DYN365_CUSTOMER_VOICE_ADDON" 'Dynamics 365 Customer Voice Base Plan' = "Customer_Voice_Base" 'Dynamics 365 Customer Voice Trial' = "FORMS_PRO" 'Dynamics 365 Customer Voice USL' = "Forms_Pro_USL" 'Dynamics 365 Enterprise Edition - Additional Portal (Qualified Offer)' = "CRM_ONLINE_PORTAL" 'Dynamics 365 Field Service Enterprise vTrial' = "DYN365_FS_ENTERPRISE_VIRAL_TRIAL" 'Dynamics 365 Field Service Viral Trial' = "Dynamics_365_Field_Service_Enterprise_viral_trial" 'Dynamics 365 Field Service, Enterprise Edition - Resource Scheduling Optimization' = "CRM_AUTO_ROUTING_ADDON" 'Dynamics 365 Finance' = "DYN365_FINANCE" 'Dynamics 365 for Business Central Essentials' = "DYN365_FINANCIALS_BUSINESS" 'Dynamics 365 for Case Management' = "DYN365_ENTERPRISE_CASE_MANAGEMENT" 'Dynamics 365 for Case Management Enterprise Edition' = "DYN365_ENTERPRISE_CASE_MANAGEMENT" 'Dynamics 365 for Customer Service' = "DYN365_ENTERPRISE_CUSTOMER_SERVICE" 'Dynamics 365 for Customer Service Chat' = "DYN365_CS_CHAT" 'Dynamics 365 for Customer Service Enterprise Attach' = "D365_CUSTOMER_SERVICE_ENT_ATTACH" 'Dynamics 365 for Customer Service Enterprise Attach to Qualifying Dynamics 365 Base Offer A' = "D365_CUSTOMER_SERVICE_ENT_ATTACH" 'Dynamics 365 for Customer Service Enterprise Edition' = "DYN365_ENTERPRISE_CUSTOMER_SERVICE" 'Dynamics 365 for Customer Service Pro' = "DYN365_CUSTOMER_SERVICE_PRO" 'Dynamics 365 for Customer Service Voice Add-in' = "DYN365_CS_VOICE" 'Dynamics 365 for Field Service' = "DYN365_ENTERPRISE_FIELD_SERVICE" 'Dynamics 365 for Field Service Attach' = "D365_FIELD_SERVICE_ATTACH" 'Dynamics 365 for Field Service Attach to Qualifying Dynamics 365 Base Offer' = "D365_FIELD_SERVICE_ATTACH" 'Dynamics 365 for Field Service Enterprise Edition' = "DYN365_ENTERPRISE_FIELD_SERVICE" 'Dynamics 365 for Finance and Operations Enterprise edition - Regulatory Service' = "DYN365_REGULATORY_SERVICE" 'DYNAMICS 365 FOR FINANCIALS' = "POWERAPPS_DYN_APPS" 'Dynamics 365 for Financials Business Edition' = "DYN365_FINANCIALS_BUSINESS_SKU" 'Dynamics 365 for HCM Trial' = "Dynamics_365_for_HCM_Trial" 'Dynamics 365 for Marketing' = "DYN365_MARKETING_APP" 'Dynamics 365 for Marketing 50K Addnl Contacts' = "DYN365_MARKETING_50K_CONTACT_ADDON" 'Dynamics 365 for Marketing Additional Application' = "DYN365_MARKETING_APPLICATION_ADDON" 'Dynamics 365 for Marketing Additional Non-Prod Application' = "DYN365_MARKETING_SANDBOX_APPLICATION_ADDON" 'Dynamics 365 for Marketing Addnl Contacts Tier 3' = "DYN365_MARKETING_CONTACT_ADDON_T3" 'Dynamics 365 for Marketing Addnl Contacts Tier 5' = "DYN365_MARKETING_CONTACT_ADDON_T5" 'Dynamics 365 for Marketing Attach' = "DYN365_MARKETING_APP_ATTACH" 'Dynamics 365 for Marketing Business Edition' = "DYN365_BUSINESS_MARKETING" 'Dynamics 365 for Marketing MSE User' = "DYN365_MARKETING_MSE_USER" 'Dynamics 365 for Marketing USL' = "D365_MARKETING_USER" 'Dynamics 365 for Operations Devices' = "Dynamics_365_for_OperationsDevices" 'Dynamics 365 for Operations Enterprise Edition - Sandbox Tier 4:Standard Performance Testing' = "Dynamics_365_for_Operations_Sandbox_Tier4" 'Dynamics 365 for Operations non-production multi-box instance for standard acceptance testing (Tier 2)' = "Dynamics_365_for_Operations_Sandbox_Tier2" 'DYNAMICS 365 FOR OPERATIONS TEAM MEMBERS' = "DYNAMICS_365_FOR_OPERATIONS_TEAM_MEMBERS" 'DYNAMICS 365 FOR RETAIL' = "Dynamics_365_for_Retail" 'Dynamics 365 for Retail Device' = "DYN365_RETAIL_DEVICE" 'DYNAMICS 365 FOR RETAIL TEAM MEMBERS' = "Dynamics_365_for_Retail_Team_members" 'Dynamics 365 for Retail Trial' = "DYN365_RETAIL_TRIAL" 'DYNAMICS 365 FOR SALES' = "DYN365_ENTERPRISE_SALES" 'Dynamics 365 for Sales and Customer Service Enterprise Edition' = "DYN365_ENTERPRISE_SALES_CUSTOMERSERVICE" 'Dynamics 365 for Sales Enterprise Attach' = "D365_SALES_ENT_ATTACH" 'Dynamics 365 for Sales Enterprise Edition' = "DYN365_ENTERPRISE_SALES" 'Dynamics 365 for Sales Pro Attach' = "D365_SALES_PRO_ATTACH" 'Dynamics 365 For Sales Professional' = "D365_SALES_PRO" 'Dynamics 365 For Sales Professional Trial' = "D365_SALES_PRO_IW" 'Dynamics 365 for Supply Chain Management' = "DYN365_SCM" 'Dynamics 365 for Talent' = "SKU_Dynamics_365_for_HCM_Trial" 'DYNAMICS 365 FOR TALENT - ATTRACT EXPERIENCE TEAM MEMBER' = "DYN365_Enterprise_Talent_Attract_TeamMember" 'DYNAMICS 365 FOR TALENT - ONBOARD EXPERIENCE' = "DYN365_Enterprise_Talent_Onboard_TeamMember" 'DYNAMICS 365 FOR TALENT TEAM MEMBERS' = "Dynamics_365_for_Talent_Team_members" 'Dynamics 365 for Talent: Attract' = "Dynamics_365_Hiring_Free_PLAN" 'Dynamics 365 for Talent: Onboard' = "Dynamics_365_Onboarding_Free_PLAN" 'Dynamics 365 for Team Members' = "DYN365_FINANCIALS_TEAM_MEMBERS" 'Dynamics 365 for Team Members Enterprise Edition' = "DYN365_ENTERPRISE_TEAM_MEMBERS" 'DYNAMICS 365 FOR_OPERATIONS' = "Dynamics_365_for_Operations" 'Dynamics 365 Guides' = "GUIDES_USER" 'DYNAMICS 365 HIRING FREE PLAN' = "DYNAMICS_365_HIRING_FREE_PLAN" 'Dynamics 365 Hybrid Connector' = "CRM_HYBRIDCONNECTOR" 'Dynamics 365 Marketing' = "DYN365_BUSINESS_Marketing" 'Dynamics 365 Marketing Sandbox Application AddOn' = "DYN365_MARKETING_SANDBOX_APPLICATION_ADDON" 'Dynamics 365 Operations - Device' = "Dynamics_365_for_Operations_Devices" 'Dynamics 365 Operations - Sandbox Tier 2:Standard Acceptance Testing' = "Dynamics_365_for_Operations_Sandbox_Tier2_SKU" 'Dynamics 365 Operations - Sandbox Tier 4:Standard Performance Testing' = "Dynamics_365_for_Operations_Sandbox_Tier4_SKU" 'Dynamics 365 Operations Trial Environment' = "ERP_TRIAL_INSTANCE" 'Dynamics 365 P1' = "DYN365_ENTERPRISE_P1" 'Dynamics 365 P1 Tria for Information Workers' = "DYN365_ENTERPRISE_P1_IW" 'DYNAMICS 365 P1 TRIAL FOR INFORMATION WORKERS' = "DYN365_ENTERPRISE_P1_IW" 'Dynamics 365 Project Operations' = "D365_ProjectOperations" 'Dynamics 365 Project Operations CDS' = "D365_ProjectOperationsCDS" 'Dynamics 365 Regulatory Service - Enterprise Edition Trial' = "DYN365_REGULATORY_SERVICE" 'Dynamics 365 Remote Assist' = "MICROSOFT_REMOTE_ASSIST" 'Dynamics 365 Remote Assist HoloLens' = "MICROSOFT_REMOTE_ASSIST_HOLOLENS" 'Dynamics 365 Sales Enterprise Attach to Qualifying Dynamics 365 Base Offer' = "D365_SALES_ENT_ATTACH" 'Dynamics 365 Sales Enterprise vTrial' = "DYN365_SALES_ENTERPRISE_VIRAL_TRIAL" 'Dynamics 365 Sales Insights vTrial' = "DYN365_SALES_INSIGHTS_VIRAL_TRIAL" 'Dynamics 365 Sales Premium' = "DYN365_SALES_PREMIUM" 'Dynamics 365 Sales Premium Viral Trial' = "Dynamics_365_Sales_Premium_Viral_Trial" 'Dynamics 365 Sales Professional Attach to Qualifying Dynamics 365 Base Offer' = "D365_SALES_PRO_ATTACH" 'Dynamics 365 Sales, Field Service and Customer Service Partner Sandbox' = "Dynamics_365_Sales_Field_Service_and_Customer_Service_Partner_Sandbox" 'Dynamics 365 Talent: Attract' = "Dynamics_365_Hiring_SKU" 'Dynamics 365 Talent: Onboard' = "DYNAMICS_365_ONBOARDING_SKU" 'Dynamics 365 Team Members' = "DYN365_TEAM_MEMBERS" 'Dynamics 365 UNF OPS Plan ENT Edition' = "Dynamics_365_for_Operations" 'Dynamics Customer Voice Add-On' = "CUSTOMER_VOICE_ADDON" 'Education Analytics' = "EducationAnalyticsP1" 'Enterprise Mobility + Security A3 for Faculty' = "EMS_EDU_FACULTY" 'Enterprise Mobility + Security E3' = "EMS" 'Enterprise Mobility + Security E5' = "EMSPREMIUM" 'Enterprise Mobility + Security G3 GCC' = "EMS_GOV" 'Enterprise Mobility + Security G5 GCC' = "EMSPREMIUM_GOV" 'EQUIVIO_ANALYTICS_GOV' = "EQUIVIO_ANALYTICS_GOV" 'Exchange Enterprise CAL Services (EOP DLP)' = "EOP_ENTERPRISE_PREMIUM" 'EXCHANGE ESSENTIALS' = "EXCHANGE_S_ESSENTIALS" 'Exchange Foundation' = "EXCHANGE_S_FOUNDATION" 'Exchange Foundation for Government' = "EXCHANGE_S_FOUNDATION_GOV" 'Exchange Online (Kiosk) for Government' = "EXCHANGE_S_DESKLESS_GOV" 'EXCHANGE ONLINE (P1)' = "EXCHANGE_L_STANDARD" 'Exchange Online (Plan 1)' = "EXCHANGESTANDARD" 'Exchange Online (Plan 1) for Alumni with Yammer' = "EXCHANGESTANDARD_ALUMNI" 'Exchange Online (Plan 1) for GCC' = "EXCHANGESTANDARD_GOV" 'Exchange Online (Plan 1) for Government' = "EXCHANGE_S_STANDARD_GOV" 'Exchange Online (Plan 1) for Students' = "EXCHANGESTANDARD_STUDENT" 'Exchange Online (Plan 2)' = "EXCHANGEENTERPRISE" 'Exchange Online (Plan 2) for Faculty' = "EXCHANGEENTERPRISE_FACULTY" 'Exchange Online (Plan 2) for Government' = "EXCHANGE_S_ENTERPRISE_GOV" 'Exchange Online Archiving' = "EXCHANGE_S_ARCHIVE_ADDON" 'Exchange Online Archiving for Exchange Online' = "EXCHANGEARCHIVE_ADDON" 'Exchange Online Archiving for Exchange Server' = "EXCHANGEARCHIVE" 'Exchange Online Essentials' = "EXCHANGE_S_ESSENTIALS" 'Exchange Online Essentials (ExO P1 Based)' = "EXCHANGEESSENTIALS" 'Exchange Online Kiosk' = "EXCHANGEDESKLESS" 'Exchange Online Multi-Geo' = "EXCHANGEONLINE_MULTIGEO" 'EXCHANGE ONLINE PLAN' = "EXCHANGE_S_STANDARD_MIDMARKET" 'Exchange Online POP' = "EXCHANGETELCO" 'Exchange Online Protection' = "EOP_ENTERPRISE" 'EXCHANGE PLAN 2G' = "EXCHANGE_S_ENTERPRISE_GOV" 'EXCHANGE_ANALYTICS_GOV' = "EXCHANGE_ANALYTICS_GOV" 'EXCHANGE_S_DESKLESS' = "EXCHANGE_S_DESKLESS" 'EXCHANGE_S_ENTERPRISE_GOV' = "EXCHANGE_S_ENTERPRISE_GOV" 'EXCHANGE_S_FOUNDATION' = "EXCHANGE_S_FOUNDATION" 'EXCHANGE_S_FOUNDATION_GOV' = "EXCHANGE_S_FOUNDATION_GOV" 'Field Service � Automated Routing Engine Add-On' = "CRM_AUTO_ROUTING_ENGINE_ADDON" 'Flow for CCI Bots' = "FLOW_CCI_BOTS" 'Flow for Developer' = "FLOW_DEV_VIRAL" 'FLOW FOR DYNAMICS 36' = "FLOW_DYN_P2" 'Flow for Dynamics 365' = "FLOW_DYN_APPS" 'FLOW FOR OFFICE 365' = "FLOW_O365_P1" 'Flow for Project' = "FLOW_FOR_PROJECT" 'Flow Free' = "FLOW_P2_VIRAL" 'Flow P2 Viral' = "FLOW_P2_VIRAL_REAL" 'Flow per app baseline access' = "Flow_Per_APP_IWTRIAL" 'Flow per business process plan' = "FLOW_BUSINESS_PROCESS" 'Flow per user plan' = "FLOW_PER_USER" 'FLOW_O365_P3_GOV' = "FLOW_O365_P3_GOV" 'Forms for Government (Plan E1)' = "FORMS_GOV_E1" 'FORMS FOR GOVERNMENT (PLAN E3)' = "FORMS_GOV_E3" 'Forms for Government (Plan F1)' = "FORMS_GOV_F1" 'FORMS_GOV_E5' = "FORMS_GOV_E5" 'Graph Connectors Search with Index' = "GRAPH_CONNECTORS_SEARCH_INDEX" 'Graph Connectors Search with Index (Microsoft Viva Topics)' = "GRAPH_CONNECTORS_SEARCH_INDEX_TOPICEXP" 'Graph Connectors Search with Index (Viva Topics)' = "GRAPH_CONNECTORS_SEARCH_INDEX_TOPICEXP" 'INFO_GOVERNANCE' = "INFO_GOVERNANCE" 'Information Barriers' = "INFORMATION_BARRIERS" 'Information Protection and Governance Analytics � Premium' = "Content_Explorer" 'Information Protection and Governance Analytics - Premium' = "Content_Explorer" 'Information Protection and Governance Analytics - Premium)' = "Content_Explorer" 'Information Protection and Governance Analytics � Standard' = "ContentExplorer_Standard" 'Information Protection and Governance Analytics - Standard' = "ContentExplorer_Standard" 'Information Protection and Governance Analytics -Premium' = "Content_Explorer" 'Information Protection for Office 365 - Premium' = "MIP_S_CLP2" 'Information Protection for Office 365 - Standard' = "MIP_S_CLP1" 'INFORMATION_BARRIERS' = "INFORMATION_BARRIERS" 'Insights by MyAnalytics' = "MYANALYTICS_P2" 'INSIGHTS BY MYANALYTICS FOR GOVERNMENT' = "MYANALYTICS_P2_GOV" 'Intune' = "INTUNE_A" 'Intune Advanced endpoint analytics' = "Intune_AdvancedEA" 'Intune Endpoint Privilege Management' = "Intune-EPM" 'Intune for Education' = "INTUNE_EDU" 'Intune Plan 2' = "INTUNE_P2" 'INTUNE_A' = "INTUNE_A" 'INTUNE_O365' = "INTUNE_O365" 'IoT Intelligence Add-in Additional Machines' = "D365_IOTFORSCM_ADDITIONAL" 'Iot Intelligence Add-in for D365 Supply Chain Management' = "D365_IOTFORSCM" 'LOCKBOX_ENTERPRISE_GOV' = "LOCKBOX_ENTERPRISE_GOV" 'LOGIC FLOWS' = "POWERFLOWSFREE" 'M365 Communication Compliance' = "MICROSOFT_COMMUNICATION_COMPLIANCE" 'M365_ADVANCED_AUDITING' = "M365_ADVANCED_AUDITING" 'MCO FREE FOR MICROSOFT TEAMS (FREE)' = "MCOFREE" 'MCOEV_GOV' = "MCOEV_GOV" 'MCOIMP' = "MCOIMP" 'MCOMEETADV_GOV' = "MCOMEETADV_GOV" 'MCOPSTN3' = "MCOPSTN3" 'MCOSTANDARD_GOV' = "MCOSTANDARD_GOV" 'MCS - BizApps_Cloud for Sustainability_vTrial' = "MCS_BizApps_Cloud_for_Sustainability_vTrial" 'MDE_SecurityManagement' = "Intune_Defender" 'Meeting Room Managed Services' = "MMR_P1" 'MFA_PREMIUM' = "MFA_PREMIUM" 'Microsoft 365 A1' = "M365EDU_A1" 'Microsoft 365 A3 - Unattended License for students use benefit' = "M365EDU_A3_STUUSEBNFT_RPA1" 'Microsoft 365 A3 for Faculty' = "M365EDU_A3_FACULTY" 'Microsoft 365 A3 for Students' = "M365EDU_A3_STUDENT" 'Microsoft 365 A3 for students use benefit' = "M365EDU_A3_STUUSEBNFT" 'Microsoft 365 A3 Suite features for faculty' = "Microsoft 365 A3 Suite features for faculty" 'Microsoft 365 A5 for Faculty' = "M365EDU_A5_FACULTY" 'Microsoft 365 A5 for Students' = "M365EDU_A5_STUDENT" 'Microsoft 365 A5 for students use benefit' = "M365EDU_A5_STUUSEBNFT" 'Microsoft 365 A5 Suite features for faculty' = "M365_A5_SUITE_COMPONENTS_FACULTY" 'Microsoft 365 A5 without Audio Conferencing for students use benefit' = "M365EDU_A5_NOPSTNCONF_STUUSEBNFT" 'Microsoft 365 Advanced Auditing' = "M365_ADVANCED_AUDITING" 'Microsoft 365 Advanced Communications' = "TEAMS_ADVCOMMS" 'Microsoft 365 Apps for Business' = "SMB_BUSINESS" 'Microsoft 365 Apps for Enterprise' = "OFFICESUBSCRIPTION" 'Microsoft 365 Apps for enterprise (device)' = "OFFICE_PROPLUS_DEVICE1" 'Microsoft 365 Apps for Enterprise (Unattended)' = "OFFICESUBSCRIPTION_unattended" 'Microsoft 365 Apps for enterprise G' = "OFFICESUBSCRIPTION_GOV" 'Microsoft 365 Apps for Faculty' = "OFFICESUBSCRIPTION_FACULTY" 'Microsoft 365 Apps for Students' = "OFFICESUBSCRIPTION_STUDENT" 'Microsoft 365 Audio Conferencing' = "MCOMEETADV" 'Microsoft 365 Audio Conferencing for GCC' = "MCOMEETADV_GOV" 'MICROSOFT 365 AUDIO CONFERENCING FOR GOVERNMENT' = "MCOMEETADV_GOV" 'Microsoft 365 Audio Conferencing Pay-Per-Minute' = "MCOMEETACPEA" 'Microsoft 365 Audio Conferencing Pay-Per-Minute - EA' = "MCOMEETACPEA" 'Microsoft 365 Audit Platform' = "M365_AUDIT_PLATFORM" 'Microsoft 365 Business Basic' = "SMB_BUSINESS_ESSENTIALS" 'Microsoft 365 Business Premium' = "SPB" 'Microsoft 365 Business Standard' = "O365_BUSINESS_PREMIUM" 'Microsoft 365 Business Standard - Prepaid Legacy' = "SMB_BUSINESS_PREMIUM" 'Microsoft 365 Communication Compliance' = "MICROSOFT_COMMUNICATION_COMPLIANCE" 'Microsoft 365 Defender' = "MTP" 'Microsoft 365 Domestic Calling Plan' = "MCOPSTN1" 'MICROSOFT 365 DOMESTIC CALLING PLAN (120 min)' = "MCOPSTN5" 'Microsoft 365 Domestic Calling Plan (120 min) at User Level' = "MCOPSTN8" 'Microsoft 365 Domestic Calling Plan (120 Minutes)' = "MCOPSTN_5" 'Microsoft 365 Domestic Calling Plan for GCC' = "MCOPSTN_1_GOV" 'Microsoft 365 E3' = "SPE_E3" 'Microsoft 365 E3 - Unattended License' = "SPE_E3_RPA1" 'Microsoft 365 E3 (500 seats min)_HUB' = "Microsoft_365_E3" 'Microsoft 365 E3 Extra Features' = "Microsoft_365_E3_Extra_Features" 'Microsoft 365 E3_USGOV_DOD' = "SPE_E3_USGOV_DOD" 'Microsoft 365 E3_USGOV_GCCHIGH' = "SPE_E3_USGOV_GCCHIGH" 'Microsoft 365 E5' = "SPE_E5" 'Microsoft 365 E5 (500 seats min)_HUB' = "Microsoft_365_E5" 'Microsoft 365 E5 Compliance' = "INFORMATION_PROTECTION_COMPLIANCE" 'Microsoft 365 E5 Developer (without Windows and Audio Conferencing)' = "DEVELOPERPACK_E5" 'Microsoft 365 E5 Security' = "IDENTITY_THREAT_PROTECTION" 'Microsoft 365 E5 Security for EMS E5' = "IDENTITY_THREAT_PROTECTION_FOR_EMS_E5" 'Microsoft 365 E5 Suite features' = "M365_E5_SUITE_COMPONENTS" 'Microsoft 365 E5 with Calling Minutes' = "SPE_E5_CALLINGMINUTES" 'Microsoft 365 E5 without Audio Conferencing' = "SPE_E5_NOPSTNCONF" 'Microsoft 365 E5 without Audio Conferencing (500 seats min)_HUB' = "Microsoft_365_E5_without_Audio_Conferencing" 'Microsoft 365 F1' = "M365_F1_COMM" 'Microsoft 365 F3' = "SPE_F1" 'Microsoft 365 F3 GCC' = "M365_F1_GOV" 'Microsoft 365 F5 Compliance Add-on' = "SPE_F5_COMP" 'Microsoft 365 F5 Compliance Add-on AR (DOD)_USGOV_DOD' = "SPE_F5_COMP_AR_D_USGOV_DOD" 'Microsoft 365 F5 Compliance Add-on AR_USGOV_GCCHIGH' = "SPE_F5_COMP_AR_USGOV_GCCHIGH" 'Microsoft 365 F5 Compliance Add-on GCC' = "SPE_F5_COMP_GCC" 'Microsoft 365 F5 Security + Compliance Add-on' = "SPE_F5_SECCOMP" 'Microsoft 365 F5 Security Add-on' = "SPE_F5_SEC" 'Microsoft 365 G3 GCC' = "M365_G3_GOV" 'Microsoft 365 GCC G5' = "M365_G5_GCC" 'Microsoft 365 Lighthouse' = "Microsoft365_Lighthouse" 'Microsoft 365 Lighthouse (Plan 1)' = "M365_LIGHTHOUSE_CUSTOMER_PLAN1" 'Microsoft 365 Lighthouse (Plan 2)' = "M365_LIGHTHOUSE_PARTNER_PLAN1" 'Microsoft 365 Phone Standard Resource Account' = "MCOEV_VIRTUALUSER" 'Microsoft 365 Phone Standard Resource Account for Government' = "MCOEV_VIRTUALUSER_GOV" 'MICROSOFT 365 PHONE SYSTE' = "MCOEV" 'Microsoft 365 Phone System' = "MCOEV" 'Microsoft 365 Phone System for Government' = "MCOEV_GOV" 'Microsoft 365 Security and Compliance for Firstline Workers' = "M365_SECURITY_COMPLIANCE_FOR_FLW" 'Microsoft Application Protection and Governance (A)' = "MICROSOFT_APPLICATION_PROTECTION_AND_GOVERNANCE_A" 'Microsoft Application Protection and Governance (D)' = "MICROSOFT_APPLICATION_PROTECTION_AND_GOVERNANCE_D" 'MICROSOFT AZURE ACTIVE DIRECTORY BASIC' = "AAD_BASIC" 'MICROSOFT AZURE ACTIVE DIRECTORY RIGHTS' = "RMS_S_PREMIUM" 'Microsoft Azure Multi-Factor Authentication' = "MFA_STANDALONE" 'Microsoft Azure Rights Management Service' = "RMS_S_BASIC" 'Microsoft Bookings' = "MICROSOFTBOOKINGS" 'Microsoft Business Center' = "MICROSOFT_BUSINESS_CENTER" 'Microsoft Cloud App Security' = "ADALLOM_STANDALONE" 'Microsoft Cloud for Sustainability vTrial' = "Microsoft_Cloud_for_Sustainability_vTrial" 'Microsoft Communications Compliance' = "COMMUNICATIONS_COMPLIANCE" 'Microsoft Communications DLP' = "COMMUNICATIONS_DLP" 'Microsoft Customer Key' = "CUSTOMER_KEY" 'Microsoft Data Investigations' = "DATA_INVESTIGATIONS" 'Microsoft Defender for Business' = "MDE_SMB" 'Microsoft Defender for Cloud Apps' = "ADALLOM_S_STANDALONE" 'Microsoft Defender for Cloud Apps Discovery' = "ADALLOM_S_DISCOVERY" 'Microsoft Defender for Cloud Apps for DOD' = "ADALLOM_S_STANDALONE_DOD" 'Microsoft Defender for Endpoint' = "WIN_DEF_ATP" 'Microsoft Defender for Endpoint P1' = "DEFENDER_ENDPOINT_P1" 'Microsoft Defender for Endpoint P1 for EDU' = "DEFENDER_ENDPOINT_P1_EDU" 'Microsoft Defender for Endpoint P2_XPLAT' = "MDATP_XPLAT" 'Microsoft Defender for Endpoint Plan 1' = "MDE_LITE" 'Microsoft Defender for Endpoint Server' = "MDATP_Server" 'Microsoft Defender for Identity' = "ATA" 'Microsoft Defender for Office 365 (Plan 1)' = "ATP_ENTERPRISE" 'Microsoft Defender for Office 365 (Plan 1) Faculty' = "ATP_ENTERPRISE_FACULTY" 'Microsoft Defender for Office 365 (Plan 1) for Government' = "ATP_ENTERPRISE_GOV" 'Microsoft Defender for Office 365 (Plan 1) GCC' = "ATP_ENTERPRISE_GOV" 'Microsoft Defender for Office 365 (Plan 2)' = "THREAT_INTELLIGENCE" 'Microsoft Defender for Office 365 (Plan 2) for Government' = "THREAT_INTELLIGENCE_GOV" 'Microsoft Defender for Office 365 (Plan 2) GCC' = "THREAT_INTELLIGENCE_GOV" 'Microsoft Defender Vulnerability Management' = "TVM_Premium_Standalone" 'Microsoft Defender Vulnerability Management Add-on' = "TVM_Premium_Add_on" 'Microsoft Dynamics 365 Customer Voice Add-on' = "Forms_Pro_AddOn" 'Microsoft Dynamics 365 Customer Voice for Customer Engagement Plan' = "Forms_Pro_CE" 'Microsoft Dynamics 365 Customer Voice for Customer Insights' = "Forms_Pro_Customer_Insights" 'Microsoft Dynamics 365 Customer Voice for Customer Insights App' = "Customer_Voice_Customer_Insights" 'Microsoft Dynamics 365 Customer Voice for Customer Service Enterprise' = "Forms_Pro_Service" 'Microsoft Dynamics 365 Customer Voice for Field Service' = "Forms_Pro_FS" 'Microsoft Dynamics 365 Customer Voice for Marketing' = "Forms_Pro_Marketing" 'Microsoft Dynamics 365 Customer Voice for Marketing Application' = "Forms_Pro_Marketing_App" 'Microsoft Dynamics 365 Customer Voice for Relationship Sales' = "Forms_Pro_Relationship_Sales" 'Microsoft Dynamics 365 Customer Voice for Sales Enterprise' = "Forms_Pro_SalesEnt" 'Microsoft Dynamics 365 Customer Voice USL' = "Forms_Pro_USL" 'Microsoft Dynamics 365 for Finance' = "D365_Finance" 'Microsoft Dynamics AX7 User Trial' = "AX7_USER_TRIAL" 'Microsoft Dynamics CRM Online' = "CRMSTANDARD" 'Microsoft Dynamics CRM Online - Portal Add-On' = "CRM_ONLINE_PORTAL" 'Microsoft Dynamics CRM Online Additional Test Instance' = "CRMTESTINSTANCE" 'Microsoft Dynamics CRM Online Basic' = "CRMPLAN2" 'Microsoft Dynamics CRM Online Instance' = "CRMINSTANCE" 'MICROSOFT DYNAMICS CRM ONLINE PROFESSIONA' = "CRMSTANDARD" 'Microsoft Dynamics CRM Online Storage Add-On' = "CRMSTORAGE" 'MICROSOFT DYNAMICS MARKETING SALES COLLABORATION - ELIGIBILITY CRITERIA APPLY' = "MDM_SALES_COLLABORATION" 'Microsoft eCDN' = "MICROSOFT_ECDN" 'Microsoft Endpoint DLP' = "MICROSOFTENDPOINTDLP" 'Microsoft Excel Advanced Analytics' = "EXCEL_PREMIUM" 'Microsoft Fabric (Free)' = "POWER_BI_STANDARD" 'Microsoft Fabric (Free) for faculty' = "POWER_BI_STANDARD_FACULTY" 'Microsoft Fabric (Free) for student' = "POWER_BI_STANDARD_STUDENT" 'Microsoft Forms (Plan 2)' = "OFFICE_FORMS_PLAN_2" 'Microsoft Forms (Plan 3)' = "OFFICE_FORMS_PLAN_3" 'MICROSOFT FORMS (PLAN E1)' = "FORMS_PLAN_E1" 'Microsoft Forms (Plan E3)' = "FORMS_PLAN_E3" 'Microsoft Forms (Plan E5)' = "FORMS_PLAN_E5" 'Microsoft Forms (Plan F1)' = "FORMS_PLAN_K" 'Microsoft Forms for Government (Plan E5)' = "FORMS_GOV_E5" 'Microsoft Imagine Academy' = "IT_ACADEMY_AD" 'Microsoft Information Governance' = "INFO_GOVERNANCE" 'Microsoft Insider Risk Management' = "INSIDER_RISK" 'Microsoft Intune' = "INTUNE_A" 'Microsoft Intune Device' = "INTUNE_A_D" 'Microsoft Intune Device for Government' = "INTUNE_A_D_GOV" 'Microsoft Intune for Education' = "INTUNE_EDU" 'Microsoft Intune Plan 1' = "INTUNE_A" 'Microsoft Intune Plan 1 for Education' = "INTUNE_EDU" 'Microsoft Intune SMB' = "INTUNE_SMB" 'Microsoft Intune Suite' = "Microsoft_Intune_Suite" 'Microsoft Invoicing' = "DYN365BC_MS_INVOICING" 'Microsoft Kaizala' = "KAIZALA_STANDALONE" 'Microsoft Kaizala Pro' = "KAIZALA_O365_P3" 'Microsoft Kaizala Pro Plan 1' = "KAIZALA_O365_P1" 'Microsoft Kaizala Pro Plan 2' = "KAIZALA_O365_P2" 'Microsoft Kaizala Pro Plan 3' = "KAIZALA_O365_P3" 'Microsoft ML-Based Classification' = "ML_CLASSIFICATION" 'Microsoft MyAnalytics (Full)' = "EXCHANGE_ANALYTICS" 'Microsoft MyAnalytics for Government (Full)' = "EXCHANGE_ANALYTICS_GOV" 'MICROSOFT PLANNE' = "PROJECTWORKMANAGEMENT" 'Microsoft Planner' = "PROJECTWORKMANAGEMENT" 'Microsoft Power Apps for Developer' = "POWERAPPS_DEV" 'Microsoft Power Apps Plan 2 (Qualified Offer)' = "POWERFLOW_P2" 'Microsoft Power Apps Plan 2 Trial' = "POWERAPPS_VIRAL" 'Microsoft Power Automate Free' = "FLOW_FREE" 'Microsoft Power Automate Plan 2' = "FLOW_P2" 'MICROSOFT POWER BI INFORMATION SERVICES PLAN' = "SQL_IS_SSIM" 'Microsoft Power BI Information Services Plan 1' = "SQL_IS_SSIM" 'Microsoft Power BI Reporting and Analytics Plan 1' = "BI_AZURE_P1" 'MICROSOFT POWER VIDEOS BASIC' = "POWERVIDEOSFREE" 'MICROSOFT POWERAPPS' = "POWERAPPSFREE" 'Microsoft Records Management' = "RECORDS_MANAGEMENT" 'Microsoft Relationship Sales solution' = "DYN365_ ENTERPRISE _RELATIONSHIP_SALES" 'Microsoft Remote Assist' = "MICROSOFT_REMOTE_ASSIST" 'Microsoft Search' = "MICROSOFT_SEARCH" 'MICROSOFT SOCIAL ENGAGEMENT - SERVICE DISCONTINUATION' = "DYN365_ENTERPRISE_CUSTOMER_SERVICE" 'Microsoft Social Engagement Enterprise' = "NBENTERPRISE" 'MICROSOFT SOCIAL ENGAGEMENT PROFESSIONAL - ELIGIBILITY CRITERIA APPLY' = "NBPROFESSIONALFORCRM" 'Microsoft StaffHub' = "Deskless" 'Microsoft Stream' = "STREAM" 'MICROSOFT STREAM FOR O365 E1 SKU' = "STREAM_O365_E1" 'Microsoft Stream for O365 E3 SKU' = "STREAM_O365_E3" 'MICROSOFT STREAM FOR O365 E5 SKU' = "STREAM_O365_E5" 'Microsoft Stream for O365 for Government (E1)' = "STREAM_O365_E1_GOV" 'MICROSOFT STREAM FOR O365 FOR GOVERNMENT (E3)' = "STREAM_O365_E3_GOV" 'Microsoft Stream for O365 for Government (F1)' = "STREAM_O365_K_GOV" 'Microsoft Stream for O365 K SKU' = "STREAM_O365_K" 'Microsoft Stream for Office 365 E1' = "STREAM_O365_E1" 'Microsoft Stream for Office 365 E3' = "STREAM_O365_E3" 'Microsoft Stream for Office 365 E5' = "STREAM_O365_E5" 'Microsoft Stream for Office 365 F3' = "STREAM_O365_K" 'Microsoft Stream Plan 2' = "STREAM_P2" 'Microsoft Stream Storage Add-On' = "STREAM_STORAGE" 'Microsoft Stream Storage Add-On (500 GB)' = "STREAM_STORAGE" 'Microsoft Teams' = "TEAMS1" 'Microsoft Teams (Free)' = "TEAMS_FREE" 'Microsoft Teams Audio Conferencing with dial-out to select geographies' = "MCOMEETBASIC" 'Microsoft Teams Audio Conferencing with dial-out to USA/CAN' = "Microsoft_Teams_Audio_Conferencing_select_dial_out" 'Microsoft Teams Commercial Cloud' = "TEAMS_COMMERCIAL_TRIAL" 'Microsoft Teams Essentials' = "Teams_Ess" 'Microsoft Teams Essentials (AAD Identity)' = "TEAMS_ESSENTIALS_AAD" 'Microsoft Teams Exploratory' = "TEAMS_EXPLORATORY" 'Microsoft Teams for DOD (AR)' = "TEAMS_AR_DOD" 'Microsoft Teams for GCCHigh (AR)' = "TEAMS_AR_GCCHIGH" 'Microsoft Teams for Government' = "TEAMS_GOV" 'Microsoft Teams Phone Resource Account' = "PHONESYSTEM_VIRTUALUSER" 'Microsoft Teams Phone Resource Account for GCC' = "PHONESYSTEM_VIRTUALUSER_GOV" 'Microsoft Teams Phone Standard' = "MCOEV" 'Microsoft Teams Phone Standard for DOD' = "MCOEV_DOD" 'Microsoft Teams Phone Standard for Faculty' = "MCOEV_FACULTY" 'Microsoft Teams Phone Standard for GCC' = "MCOEV_GOV" 'Microsoft Teams Phone Standard for GCCHIGH' = "MCOEV_GCCHIGH" 'Microsoft Teams Phone Standard for Small and Medium Business' = "MCOEVSMB_1" 'Microsoft Teams Phone Standard for Students' = "MCOEV_STUDENT" 'Microsoft Teams Phone Standard for TELSTRA' = "MCOEV_TELSTRA" 'Microsoft Teams Phone Standard_USGOV_DOD' = "MCOEV_USGOV_DOD" 'Microsoft Teams Phone Standard_USGOV_GCCHIGH' = "MCOEV_USGOV_GCCHIGH" 'Microsoft Teams Premium Intelligent' = "TEAMSPRO_MGMT" 'Microsoft Teams Premium Introductory Pricing' = "Microsoft_Teams_Premium" 'Microsoft Teams Premium Personalized' = "TEAMSPRO_CUST" 'Microsoft Teams Premium Secure' = "TEAMSPRO_PROTECTION" 'Microsoft Teams Premium Virtual Appointment' = "TEAMSPRO_VIRTUALAPPT" 'Microsoft Teams Premium Virtual Appointments' = "MCO_VIRTUAL_APPT" 'Microsoft Teams Premium Webinar' = "TEAMSPRO_WEBINAR" 'Microsoft Teams Rooms Basic' = "Microsoft_Teams_Rooms_Basic" 'Microsoft Teams Rooms Basic for EDU' = "Microsoft_Teams_Rooms_Basic_FAC" 'Microsoft Teams Rooms Basic without Audio Conferencing' = "Microsoft_Teams_Rooms_Basic_without_Audio_Conferencing" 'Microsoft Teams Rooms Pro' = "Microsoft_Teams_Rooms_Pro" 'Microsoft Teams Rooms Pro for EDU' = "Microsoft_Teams_Rooms_Pro_FAC" 'Microsoft Teams Rooms Pro Management' = "MTRProManagement" 'Microsoft Teams Rooms Pro without Audio Conferencing' = "Microsoft_Teams_Rooms_Pro_without_Audio_Conferencing" 'Microsoft Teams Rooms Standard' = "MEETING_ROOM" 'Microsoft Teams Rooms Standard without Audio Conferencing' = "MEETING_ROOM_NOAUDIOCONF" 'Microsoft Teams Shared Devices' = "MCOCAP" 'Microsoft Teams Shared Devices for GCC' = "MCOCAP_GOV" 'Microsoft Teams Trial' = "MS_TEAMS_IW" 'Microsoft Threat Experts - Experts on Demand' = "EXPERTS_ON_DEMAND" 'Microsoft Tunnel for Mobile Application Management' = "Intune-MAMTunnel" 'Microsoft Viva Goals' = "Microsoft_Viva_Goals" 'Microsoft Viva Insights' = "WORKPLACE_ANALYTICS_INSIGHTS_USER" 'Microsoft Viva Insights Backend' = "WORKPLACE_ANALYTICS_INSIGHTS_BACKEND" 'Microsoft Viva Sales Premium & Trial' = "Microsoft_Viva_Sales_PremiumTrial" 'Microsoft Viva Sales Premium with Power Automate' = "Microsoft_Viva_Sales_PowerAutomate" 'Microsoft Viva Suite' = "VIVA" 'Microsoft Viva Topics' = "CORTEX" 'Microsoft Workplace Analytics' = "WORKPLACE_ANALYTICS" 'Microsoft Workplace Analytics Insights Backend' = "WORKPLACE_ANALYTICS_INSIGHTS_BACKEND" 'Microsoft Workplace Analytics Insights User' = "WORKPLACE_ANALYTICS_INSIGHTS_USER" 'MICROSOFT_COMMUNICATION_COMPLIANCE' = "MICROSOFT_COMMUNICATION_COMPLIANCE" 'MICROSOFT_SEARCH' = "MICROSOFT_SEARCH" 'MICROSOFTBOOKINGS' = "MICROSOFTBOOKINGS" 'Minecraft Education' = "MINECRAFT_EDUCATION_EDITION" 'Minecraft Education Edition' = "MINECRAFT_EDUCATION_EDITION" 'Minecraft Education Faculty' = "MEE_FACULTY" 'Minecraft Education Student' = "MEE_STUDENT" 'MIP_S_CLP1' = "MIP_S_CLP1" 'MIP_S_CLP2' = "MIP_S_CLP2" 'Mobile Device Management for Office 365' = "INTUNE_O365" 'MS IMAGINE ACADEMY' = "IT_ACADEMY_AD" 'MTP' = "MTP" 'Multi-Geo Capabilities in Office 365' = "OFFICE365_MULTIGEO" 'Nonprofit Portal' = "NONPROFIT_PORTAL" 'Nucleus' = "Nucleus" 'Office 365 A1 for faculty' = "STANDARDWOFFPACK_FACULTY" 'Office 365 A1 for students' = "STANDARDWOFFPACK_STUDENT" 'Office 365 A1 Plus for faculty' = "STANDARDWOFFPACK_IW_FACULTY" 'Office 365 A1 Plus for students' = "STANDARDWOFFPACK_IW_STUDENT" 'Office 365 A3 for faculty' = "ENTERPRISEPACKPLUS_FACULTY" 'Office 365 A3 for students' = "ENTERPRISEPACKPLUS_STUDENT" 'Office 365 A5 for faculty' = "ENTERPRISEPREMIUM_FACULTY" 'Office 365 A5 for students' = "ENTERPRISEPREMIUM_STUDENT" 'Office 365 Advanced Compliance' = "EQUIVIO_ANALYTICS" 'Office 365 Advanced Compliance for GCC' = "EQUIVIO_ANALYTICS_GOV" 'Office 365 Advanced eDiscovery' = "EQUIVIO_ANALYTICS" 'Office 365 Advanced eDiscovery for Government' = "EQUIVIO_ANALYTICS_GOV" 'Office 365 Advanced Security Management' = "ADALLOM_S_O365" 'OFFICE 365 BUSINESS' = "OFFICE_BUSINESS" 'Office 365 Cloud App Security' = "ADALLOM_O365" 'Office 365 E1' = "STANDARDPACK" 'Office 365 E2' = "STANDARDWOFFPACK" 'Office 365 E3' = "ENTERPRISEPACK" 'Office 365 E3 Developer' = "DEVELOPERPACK" 'Office 365 E3_USGOV_DOD' = "ENTERPRISEPACK_USGOV_DOD" 'Office 365 E3_USGOV_GCCHIGH' = "ENTERPRISEPACK_USGOV_GCCHIGH" 'Office 365 E4' = "ENTERPRISEWITHSCAL" 'Office 365 E5' = "ENTERPRISEPREMIUM" 'Office 365 E5 Without Audio Conferencing' = "ENTERPRISEPREMIUM_NOPSTNCONF" 'Office 365 Extra File Storage' = "SHAREPOINTSTORAGE" 'Office 365 Extra File Storage for GCC' = "SHAREPOINTSTORAGE_GOV" 'Office 365 F3' = "DESKLESSPACK" 'Office 365 G1 GCC' = "STANDARDPACK_GOV" 'Office 365 G3 GCC' = "ENTERPRISEPACK_GOV" 'Office 365 G5 GCC' = "ENTERPRISEPREMIUM_GOV" 'Office 365 Midsize Business' = "MIDSIZEPACK" 'Office 365 Planner for Government' = "PROJECTWORKMANAGEMENT_GOV" 'Office 365 Privileged Access Management' = "PAM_ENTERPRISE" 'Office 365 ProPlus' = "OFFICESUBSCRIPTION" 'Office 365 SafeDocs' = "SAFEDOCS" 'Office 365 Small Business' = "LITEPACK" 'Office 365 Small Business Premium' = "LITEPACK_P2" 'OFFICE 365 SMALL BUSINESS SUBSCRIPTION' = "OFFICE_PRO_PLUS_SUBSCRIPTION_SMBIZ" 'Office for the web' = "SHAREPOINTWAC" 'Office for the web (Education)' = "SHAREPOINTWAC_EDU" 'OFFICE FOR THE WEB (GOVERNMENT)' = "SHAREPOINTWAC_GOV" 'Office for the Web for Education' = "SHAREPOINTWAC_EDU" 'Office for the Web for Government' = "SHAREPOINTWAC_GOV" 'Office Mobile Apps for Office 365' = "OFFICEMOBILE_SUBSCRIPTION" 'Office Mobile Apps for Office 365 for GCC' = "OFFICEMOBILE_SUBSCRIPTION_GOV" 'OFFICE ONLINE' = "SHAREPOINTWAC" 'OFFICE ONLINE FOR DEVELOPER' = "SHAREPOINTWAC_DEVELOPER" 'Office Shared Computer Activation' = "OFFICE_SHARED_COMPUTER_ACTIVATION" 'OFFICEMOBILE_SUBSCRIPTION' = "OFFICEMOBILE_SUBSCRIPTION" 'OFFICESUBSCRIPTION' = "OFFICESUBSCRIPTION" 'OFFICESUBSCRIPTION_GOV' = "OFFICESUBSCRIPTION_GOV" 'OneDrive for Business (Basic 2)' = "ONEDRIVE_BASIC_P2" 'OneDrive for Business (Basic)' = "ONEDRIVE_BASIC" 'OneDrive for Business (Plan 1)' = "WACONEDRIVESTANDARD" 'OneDrive for Business (Plan 2)' = "WACONEDRIVEENTERPRISE" 'OneDrive for business Basic' = "ONEDRIVE_BASIC" 'ONEDRIVE FOR BUSINESS BASIC FOR GOVERNMENT' = "ONEDRIVE_BASIC_GOV" 'ONEDRIVEENTERPRISE' = "ONEDRIVEENTERPRISE" 'ONEDRIVESTANDARD' = "ONEDRIVESTANDARD" 'OUTLOOK CUSTOMER MANAGER' = "O365_SB_Relationship_Management" 'PAD for Windows' = "POWERAUTOMATE_DESKTOP_FOR_WIN" 'Power Apps (Plan 2)' = "POWERAPPS_P2" 'Power Apps and Logic Flows' = "POWERAPPS_INDIVIDUAL_USER" 'Power Apps for Customer Service Pro' = "POWERAPPS_CUSTOMER_SERVICE_PRO" 'Power Apps for Dynamics 365' = "POWERAPPS_DYN_TEAM" 'Power Apps for Dynamics 365 vTrial' = "POWER_APPS_DYN365_VIRAL_TRIAL" 'Power Apps for Guides' = "POWERAPPS_GUIDES" 'Power Apps for Office 365' = "POWERAPPS_O365_P2" 'Power Apps for Office 365 (Plan 3)' = "POWERAPPS_O365_P3" 'Power Apps for Office 365 F3' = "POWERAPPS_O365_S1" 'Power Apps for Office 365 F3 for Government' = "POWERAPPS_O365_S1_GOV" 'Power Apps for Office 365 for Government' = "POWERAPPS_O365_P3_GOV" 'Power Apps for Sales Pro' = "POWERAPPS_SALES_PRO" 'Power Apps per app' = "POWERAPPS_PER_APP_NEW" 'Power Apps per app plan' = "POWERAPPS_PER_APP" 'Power Apps per app plan (1 app or portal)' = "POWERAPPS_PER_APP_NEW" 'Power Apps per user plan' = "POWERAPPS_PER_USER" 'Power Apps per user plan for Government' = "POWERAPPS_PER_USER_GCC" 'Power Apps Portals Login Capacity Add-On' = "POWERAPPS_PORTALS_LOGIN" 'Power Apps Portals Login Capacity Add-On for Government' = "POWERAPPS_PORTALS_LOGIN_GCC" 'Power Apps Portals login capacity add-on Tier 2 (10 unit min)' = "POWERAPPS_PORTALS_LOGIN_T2" 'Power Apps Portals login capacity add-on Tier 2 (10 unit min) for Government' = "POWERAPPS_PORTALS_LOGIN_T2_GCC" 'Power Apps Portals login capacity add-on Tier 3 (50 unit min)' = "POWERAPPS_PORTALS_LOGIN_T3" 'Power Apps Portals page view capacity add-on' = "POWERAPPS_PORTALS_PAGEVIEW" 'Power Apps Portals page view capacity add-on for Government' = "POWERAPPS_PORTALS_PAGEVIEW_GCC" 'Power Automate (Plan 1) for Government' = "FLOW_P1_GOV" 'Power Automate (Plan 2)' = "FLOW_P2" 'Power Automate for Customer Service Pro' = "FLOW_CUSTOMER_SERVICE_PRO" 'Power Automate for Dynamics 365' = "FLOW_DYN_TEAM" 'Power Automate for Dynamics 365 Customer Voice' = "FLOW_FORMS_PRO" 'Power Automate for Dynamics 365 vTrial' = "POWER_AUTOMATE_DYN365_VIRAL_TRIAL" 'Power Automate for Office 365' = "FLOW_O365_P2" 'Power Automate for Office 365 F3' = "FLOW_O365_S1" 'Power Automate for Office 365 F3 for Government' = "FLOW_O365_S1_GOV" 'Power Automate for Office 365 for Government' = "FLOW_O365_P3_GOV" 'Power Automate for Power Apps per App Plan' = "Flow_Per_APP" 'Power Automate for Power Apps per User Plan' = "Flow_PowerApps_PerUser" 'Power Automate for Power Apps per User Plan for GCC' = "Flow_PowerApps_PerUser_GCC" 'Power Automate for Project' = "FLOW_FOR_PROJECT" 'POWER AUTOMATE FOR PROJECT P1' = "Power_Automate_For_Project_P1" 'Power Automate for Virtual Agent' = "FLOW_VIRTUAL_AGENT_BASE" 'Power Automate per flow plan' = "FLOW_BUSINESS_PROCESS" 'Power Automate per user plan' = "FLOW_PER_USER" 'Power Automate per user plan dept' = "FLOW_PER_USER_DEPT" 'Power Automate per user plan for Government' = "FLOW_PER_USER_GCC" 'Power Automate per user with attended RPA plan' = "POWERAUTOMATE_ATTENDED_RPA" 'Power Automate RPA Attended' = "POWER_AUTOMATE_ATTENDED_RPA" 'Power Automate unattended RPA add-on' = "POWERAUTOMATE_UNATTENDED_RPA" 'Power BI' = "POWER_BI_INDIVIDUAL_USER" 'Power BI (free)' = "POWER_BI_STANDARD" 'Power BI for Office 365 Add-On' = "POWER_BI_ADDON" 'Power BI Premium P' = "PBI_PREMIUM_P1_ADDON" 'Power BI Premium P1' = "PBI_PREMIUM_P1_ADDON" 'Power BI Premium Per User' = "PBI_PREMIUM_PER_USER" 'Power BI Premium Per User Add-On' = "PBI_PREMIUM_PER_USER_ADDON" 'Power BI Premium Per User Dept' = "PBI_PREMIUM_PER_USER_DEPT" 'Power BI Premium Per User for Faculty' = "PBI_PREMIUM_PER_USER_FACULTY" 'Power BI Pro' = "POWER_BI_PRO" 'Power BI Pro CE' = "POWER_BI_PRO_CE" 'Power BI Pro Dept' = "POWER_BI_PRO_DEPT" 'Power BI Pro for Faculty' = "POWER_BI_PRO_FACULTY" 'Power BI Pro for GCC' = "POWERBI_PRO_GOV" 'Power BI Pro for Government' = "BI_AZURE_P_2_GOV" 'Power Pages Internal User' = "Power_Pages_Internal_User" 'Power Pages vTrial for Makers' = "Power_Pages_vTrial_for_Makers" 'Power Virtual Agent' = "VIRTUAL_AGENT_BASE" 'Power Virtual Agent User License' = "VIRTUAL_AGENT_USL" 'Power Virtual Agents for Chat' = "POWER_VIRTUAL_AGENTS_D365_CS_CHAT" 'Power Virtual Agents for Customer Service Voice' = "POWER_VIRTUAL_AGENTS_D365_CS_VOICE" 'Power Virtual Agents for Digital Messaging' = "POWER_VIRTUAL_AGENTS_D365_CS_MESSAGING" 'Power Virtual Agents for Office 365' = "POWER_VIRTUAL_AGENTS_O365_P2" 'Power Virtual Agents for Office 365 F1' = "POWER_VIRTUAL_AGENTS_O365_F1" 'POWER VIRTUAL AGENTS FOR OFFICE 365 P1' = "POWER_VIRTUAL_AGENTS_O365_P1" 'Power Virtual Agents for Office 365 P2' = "POWER_VIRTUAL_AGENTS_O365_P2" 'Power Virtual Agents for Office 365 P3' = "POWER_VIRTUAL_AGENTS_O365_P3" 'Power Virtual Agents Viral Trial' = "CCIBOTS_PRIVPREV_VIRAL" 'PowerApps for Developer' = "POWERAPPS_DEV_VIRAL" 'PowerApps for Dynamics 365' = "POWERAPPS_DYN_APPS" 'POWERAPPS FOR OFFICE 36' = "POWERAPPS_O365_P2" 'POWERAPPS FOR OFFICE 365' = "POWERAPPS_O365_P1" 'PowerApps for Office 365 Plan 3' = "POWERAPPS_O365_P3" 'PowerApps per app baseline access' = "POWERAPPS_PER_APP_IW" 'PowerApps Plan 1 for Government' = "POWERAPPS_P1_GOV" 'PowerApps Trial' = "POWERAPPS_P2_VIRAL" 'POWERAPPS_O365_P3_GOV' = "POWERAPPS_O365_P3_GOV" 'Premium Encryption in Office 365' = "PREMIUM_ENCRYPTION" 'PREMIUM_ENCRYPTION' = "PREMIUM_ENCRYPTION" 'Priva - Risk' = "PRIVACY_MANGEMENT_RISK" 'Priva - Risk (Exchange)' = "PRIVACY_MANGEMENT_RISK_EXCHANGE" 'Privacy Management � risk' = "PRIVACY_MANAGEMENT_RISK" 'Privacy Management - risk for EDU' = "PRIVACY_MANAGEMENT_RISK_EDU" 'Privacy Management - risk GCC' = "PRIVACY_MANAGEMENT_RISK_GCC" 'Privacy Management - risk_USGOV_DOD' = "PRIVACY_MANAGEMENT_RISK_USGOV_DOD" 'Privacy Management - risk_USGOV_GCCHIGH' = "PRIVACY_MANAGEMENT_RISK_USGOV_GCCHIGH" 'Privacy Management - Subject Rights Request' = "PRIVACY_MANGEMENT_DSR" 'Privacy Management - Subject Rights Request (1 - Exchange)' = "PRIVACY_MANGEMENT_DSR_1" 'Privacy Management - subject rights request (1)' = "PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_1_V2" 'Privacy Management - subject rights request (1) for EDU' = "PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_1_EDU_V2" 'Privacy Management - subject rights request (1) GCC' = "PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_1_V2_GCC" 'Privacy Management - subject rights request (1) USGOV_DOD' = "PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_1_V2_USGOV_DOD" 'Privacy Management - subject rights request (1) USGOV_GCCHIGH' = "PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_1_V2_USGOV_GCCHIGH" 'Privacy Management - Subject Rights Request (10 - Exchange)' = "PRIVACY_MANGEMENT_DSR_EXCHANGE_10" 'Privacy Management - subject rights request (10)' = "PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_10_V2" 'Privacy Management - subject rights request (10) for EDU' = "PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_10_EDU_V2" 'Privacy Management - subject rights request (10) GCC' = "PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_10_V2_GCC" 'Privacy Management - subject rights request (10) USGOV_DOD' = "PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_10_V2_USGOV_DOD" 'Privacy Management - subject rights request (10) USGOV_GCCHIGH' = "PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_10_V2_USGOV_GCCHIGH" 'Privacy Management - Subject Rights Request (100 - Exchange)' = "PRIVACY_MANGEMENT_DSR_EXCHANGE_100" 'Privacy Management - subject rights request (100)' = "PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_100_V2" 'Privacy Management - subject rights request (100) for EDU' = "PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_100_EDU_V2" 'Privacy Management - subject rights request (100) GCC' = "PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_100_V2_GCC" 'Privacy Management - subject rights request (100) USGOV_DOD' = "PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_100_V2_USGOV_DOD" 'Privacy Management - subject rights request (100) USGOV_GCCHIGH' = "PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_100_V2_USGOV_GCCHIGH" 'Privacy Management - subject rights request (50)' = "PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_50_V2" 'Privacy Management - subject rights request (50) for EDU' = "PRIVACY_MANAGEMENT_SUB_RIGHTS_REQ_50_EDU_V2" 'Privacy Management - Subject Rights Request (Exchange)' = "PRIVACY_MANGEMENT_DSR_EXCHANGE" 'Project for Office (Plan E1)' = "PROJECT_O365_P1" 'Project for Office (Plan E3)' = "PROJECT_O365_P2" 'Project for Office (Plan E5)' = "PROJECT_O365_P3" 'Project for Office (Plan F)' = "PROJECT_O365_F3" 'Project for Office 365' = "PROJECTCLIENT" 'Project for Project Operations' = "PROJECT_FOR_PROJECT_OPERATIONS" 'Project Online Desktop Client' = "PROJECT_CLIENT_SUBSCRIPTION" 'Project Online Desktop Client for Government' = "PROJECT_CLIENT_SUBSCRIPTION_GOV" 'Project Online Essentials' = "PROJECTESSENTIALS" 'Project Online Essentials for Faculty' = "PROJECTESSENTIALS_FACULTY" 'Project Online Essentials for GCC' = "PROJECTESSENTIALS_GOV" 'Project Online Essentials for Government' = "PROJECT_ESSENTIALS_GOV" 'Project Online Premium' = "PROJECTPREMIUM" 'Project Online Premium Without Project Client' = "PROJECTONLINE_PLAN_1" 'Project Online Service' = "SHAREPOINT_PROJECT" 'Project Online Service for Education' = "SHAREPOINT_PROJECT_EDU" 'Project Online Service for Government' = "SHAREPOINT_PROJECT_GOV" 'Project Online With Project for Office 365' = "PROJECTONLINE_PLAN_2" 'PROJECT P1' = "PROJECT_P1" 'Project P3' = "PROJECT_PROFESSIONAL" 'Project P3 for Faculty' = "PROJECT_PROFESSIONAL_FACULTY" 'Project Plan 1' = "PROJECT_P1" 'Project Plan 1 (for Department)' = "PROJECT_PLAN1_DEPT" 'Project Plan 3' = "PROJECTPROFESSIONAL" 'Project Plan 3 (for Department)' = "PROJECT_PLAN3_DEPT" 'Project Plan 3 for Faculty' = "PROJECTPROFESSIONAL_FACULTY" 'Project Plan 3 for GCC' = "PROJECTPROFESSIONAL_GOV" 'Project Plan 5 for GCC' = "PROJECTPREMIUM_GOV" 'Project Plan 5 without Project Client for Faculty' = "PROJECTONLINE_PLAN_1_FACULTY" 'PROJECTWORKMANAGEMENT' = "PROJECTWORKMANAGEMENT" 'PROJECTWORKMANAGEMENT_GOV' = "PROJECTWORKMANAGEMENT_GOV" 'RECORDS_MANAGEMENT' = "RECORDS_MANAGEMENT" 'Remote help' = "REMOTE_HELP" 'RETIRED - Field Service � Automated Routing Engine Add-On' = "CRM_AUTO_ROUTING_ADDON" 'RETIRED - Microsoft Communications Compliance' = "COMMUNICATIONS_COMPLIANCE" 'RETIRED - Microsoft Insider Risk Management' = "INSIDER_RISK_MANAGEMENT" 'Retired - Microsoft Social Engagement' = "NBENTERPRISE" 'RETIRED - Outlook Customer Manager' = "O365_SB_Relationship_Management" 'Rights Management Adhoc' = "RIGHTSMANAGEMENT_ADHOC" 'Rights Management Service Basic Content Protection' = "RMSBASIC" 'RMS_S_ENTERPRISE' = "RMS_S_ENTERPRISE" 'RMS_S_ENTERPRISE_GOV' = "RMS_S_ENTERPRISE_GOV" 'RMS_S_PREMIUM' = "RMS_S_PREMIUM" 'School Data Sync (Plan 1)' = "SCHOOL_DATA_SYNC_P1" 'School Data Sync (Plan 2)' = "SCHOOL_DATA_SYNC_P2" 'SecOps Investigation for MDI' = "ADALLOM_FOR_AATP" 'Sensor Data Intelligence Additional Machines Add-in for Dynamics 365 Supply Chain Management' = "DYN365_IOT_INTELLIGENCE_ADDL_MACHINES" 'Sensor Data Intelligence Scenario Add-in for Dynamics 365 Supply Chain Management' = "DYN365_IOT_INTELLIGENCE_SCENARIO" 'SHAREPOINT' = "SHAREPOINTSTANDARD" 'SharePoint (Plan 1)' = "SHAREPOINTSTANDARD" 'SharePoint (Plan 1) for Education' = "SHAREPOINTSTANDARD_EDU" 'SharePoint (Plan 2)' = "SHAREPOINTENTERPRISE" 'SharePoint (Plan 2) for Education' = "SHAREPOINTENTERPRISE_EDU" 'SharePoint (Plan 2)Dynamics 365 for Sales Pro Attach' = "SHAREPOINTENTERPRISE" 'SHAREPOINT FOR DEVELOPER' = "SHAREPOINT_S_DEVELOPER" 'SharePoint Kiosk' = "SHAREPOINTDESKLESS" 'SharePoint KioskG' = "SHAREPOINTDESKLESS_GOV" 'SharePoint Multi-Geo' = "SHAREPOINTONLINE_MULTIGEO" 'SharePoint Online (Plan 1)' = "SHAREPOINTSTANDARD" 'SharePoint Online (Plan 2)' = "SHAREPOINTENTERPRISE" 'SharePoint Online Kiosk' = "SHAREPOINTDESKLESS" 'SHAREPOINT PLAN 1' = "SHAREPOINTENTERPRISE_MIDMARKET" 'SharePoint Plan 1G' = "SharePoint Plan 1G" 'SharePoint Plan 2 for EDU' = "SHAREPOINTENTERPRISE_EDU" 'SharePoint Plan 2G' = "SHAREPOINTENTERPRISE_GOV" 'SHAREPOINT STANDARD' = "SHAREPOINTSTANDARD" 'SharePoint Syntex' = "Intelligent_Content_Services" 'SharePoint Syntex - SPO type' = "Intelligent_Content_Services_SPO_type" 'SHAREPOINT_PROJECT' = "SHAREPOINT_PROJECT" 'SHAREPOINTDESKLESS' = "SHAREPOINTDESKLESS" 'SHAREPOINTENTERPRISE_GOV' = "SHAREPOINTENTERPRISE_GOV" 'SHAREPOINTLITE' = "SHAREPOINTLITE" 'SHAREPOINTSTANDARD' = "SHAREPOINTSTANDARD" 'SHAREPOINTSTORAGE_GOV' = "SHAREPOINTSTORAGE_GOV" 'SHAREPOINTWAC_GOV' = "SHAREPOINTWAC_GOV" 'SKYPE FOR BUSINESS CLOUD PBX FOR SMALL AND MEDIUM BUSINESS' = "MCOEVSMB" 'Skype for Business Online (Plan 1)' = "MCOIMP" 'Skype for Business Online (Plan 1) for Government' = "MCOIMP_GOV" 'Skype for Business Online (Plan 2)' = "MCOSTANDARD" 'Skype for Business Online (Plan 2) for Government' = "MCOSTANDARD_GOV" 'SKYPE FOR BUSINESS ONLINE (PLAN 2) FOR MIDSIZ' = "MCOSTANDARD_MIDMARKET" 'SKYPE FOR BUSINESS ONLINE (PLAN 3)' = "MCOVOICECONF" 'SKYPE FOR BUSINESS ONLINE (PLAN P1)' = "MCOLITE" 'Skype for Business PSTN Domestic and International Calling' = "MCOPSTN2" 'Skype for Business PSTN Domestic Calling' = "MCOPSTN1" 'Skype for Business PSTN Domestic Calling (120 Minutes)' = "MCOPSTN5" 'Skype for Business PSTN Usage Calling Plan' = "MCOPSTNPP" 'Stream for Office 365' = "STREAM_O365_SMB" 'Stream for Office 365 for Government (E5)' = "STREAM_O365_E5_GOV" 'STREAM_O365_E5_GOV' = "STREAM_O365_E5_GOV" 'STREAM_O365_K' = "STREAM_O365_K" 'Sway' = "SWAY" 'TEAMS FREE SERVICE' = "TEAMS_FREE_SERVICE" 'Teams Multi-Geo' = "TEAMSMULTIGEO" 'Teams Phone with Calling Plan' = "MCOTEAMS_ESSENTIALS" 'Teams Room Basic' = "Teams_Room_Basic" 'Teams Room Pro' = "Teams_Room_Pro" 'Teams Room Standard' = "Teams_Room_Standard" 'Teams Rooms Premium' = "MTR_PREM" 'Teams Rooms Test 1' = "Teams_Room_Basic" 'Teams Rooms Test 2' = "Teams_Room_Pro" 'TEAMS_GOV' = "TEAMS_GOV" 'TEAMS1' = "TEAMS1" 'TELSTRA Calling for O365' = "MCOPSTNEAU2" 'THREAT_INTELLIGENCE_GOV' = "THREAT_INTELLIGENCE_GOV" 'To-Do (Firstline)' = "BPOS_S_TODO_FIRSTLINE" 'To-Do (Plan 1)' = "BPOS_S_TODO_1" 'To-Do (Plan 2)' = "BPOS_S_TODO_2" 'To-Do (Plan 3)' = "BPOS_S_TODO_3" 'Universal Print' = "UNIVERSAL_PRINT" 'Universal Print Without Seeding' = "UNIVERSAL_PRINT_NO_SEEDING" 'Virtual Agent' = "VIRTUAL_AGENT_USL" 'Virtual Agent Base' = "VIRTUAL_AGENT_BASE" 'Visio Desktop App' = "VISIO_CLIENT_SUBSCRIPTION" 'VISIO DESKTOP APP FOR Government' = "VISIO_CLIENT_SUBSCRIPTION_GOV" 'Visio Online Plan 1' = "VISIOONLINE_PLAN1" 'Visio Online Plan 2' = "VISIOCLIENT" 'Visio Plan 1' = "VISIO_PLAN1_DEPT" 'Visio Plan 2' = "VISIO_PLAN2_DEPT" 'Visio Plan 2 for Faculty' = "VISIOCLIENT_FACULTY" 'Visio Plan 2 for GCC' = "VISIOCLIENT_GOV" 'Visio web app' = "VISIOONLINE" 'VISIO WEB APP FOR GOVERNMENT' = "VISIOONLINE_GOV" 'Viva Engage Communities and Communications' = "VIVAENGAGE_COMMUNITIES_AND_COMMUNICATIONS" 'Viva Engage Core' = "VIVAENGAGE_CORE" 'Viva Engage Knowledge' = "VIVAENGAGE_KNOWLEDGE" 'Viva Goals' = "Viva_Goals_Premium" 'Viva Learning' = "VIVA_LEARNING_PREMIUM" 'Viva Learning Seeded' = "VIVA_LEARNING_SEEDED" 'Viva Topics' = "TOPIC_EXPERIENCES" 'Whiteboard (Firstline)' = "WHITEBOARD_FIRSTLINE1" 'Whiteboard (Plan 1)' = "WHITEBOARD_PLAN1" 'Whiteboard (Plan 2)' = "WHITEBOARD_PLAN2" 'Whiteboard (Plan 3)' = "WHITEBOARD_PLAN3" 'WINDOWS 10 ENTERPRISE' = "WIN10_PRO_ENT_SUB" 'Windows 10 Enterprise (New)' = "Virtualization Rights for Windows 10 (E3/E5+VDA)" 'Windows 10 Enterprise E3 (Local Only)' = "WIN10_ENT_LOC_F1" 'Windows 10/11 Business' = "WINBIZ" 'Windows 10/11 Enterprise' = "Virtualization Rights for Windows 10 (E3/E5+VDA)" 'Windows 10/11 Enterprise (Original)' = "WIN10_PRO_ENT_SUB" 'Windows 10/11 Enterprise A3 for faculty' = "WIN10_ENT_A3_FAC" 'Windows 10/11 Enterprise A3 for students' = "WIN10_ENT_A3_STU" 'Windows 10/11 Enterprise A5 for faculty' = "WIN10_ENT_A5_FAC" 'Windows 10/11 Enterprise E3' = "WIN10_VDA_E3" 'Windows 10/11 Enterprise E3 VDA' = "E3_VDA_only" 'Windows 10/11 Enterprise E5' = "WIN10_VDA_E5" 'Windows 10/11 Enterprise E5 (Original)' = "WIN_ENT_E5" 'Windows 10/11 Enterprise E5 Commercial (GCC Compatible)' = "WINE5_GCC_COMPAT" 'Windows 365 Business 1 vCPU 2 GB 64 GB' = "CPC_B_1C_2RAM_64GB" 'Windows 365 Business 2 vCPU 4 GB 128 GB' = "CPC_B_2C_4RAM_128GB" 'Windows 365 Business 2 vCPU 4 GB 256 GB' = "CPC_B_2C_4RAM_256GB" 'Windows 365 Business 2 vCPU 4 GB 64 GB' = "CPC_B_2C_4RAM_64GB" 'Windows 365 Business 2 vCPU 8 GB 128 GB' = "CPC_B_2C_8RAM_128GB" 'Windows 365 Business 2 vCPU 8 GB 256 GB' = "CPC_B_2C_8RAM_256GB" 'Windows 365 Business 2 vCPU, 8 GB, 128 GB' = "CPC_SS_2" 'Windows 365 Business 4 vCPU 16 GB 128 GB' = "CPC_B_4C_16RAM_128GB" 'Windows 365 Business 4 vCPU 16 GB 128 GB (with Windows Hybrid Benefit)' = "CPC_B_4C_16RAM_128GB_WHB" 'Windows 365 Business 4 vCPU 16 GB 256 GB' = "CPC_B_4C_16RAM_256GB" 'Windows 365 Business 4 vCPU 16 GB 512 GB' = "CPC_B_4C_16RAM_512GB" 'Windows 365 Business 8 vCPU 32 GB 128 GB' = "CPC_B_8C_32RAM_128GB" 'Windows 365 Business 8 vCPU 32 GB 256 GB' = "CPC_B_8C_32RAM_256GB" 'Windows 365 Business 8 vCPU 32 GB 512 GB' = "CPC_B_8C_32RAM_512GB" 'Windows 365 Enterprise 1 vCPU 2 GB 64 GB' = "CPC_E_1C_2GB_64GB" 'Windows 365 Enterprise 2 vCPU 4 GB 128 GB' = "CPC_E_2C_4GB_128GB" 'Windows 365 Enterprise 2 vCPU 4 GB 128 GB (Preview)' = "CPC_LVL_1" 'Windows 365 Enterprise 2 vCPU 4 GB 256 GB' = "CPC_E_2C_4GB_256GB" 'Windows 365 Enterprise 2 vCPU 4 GB 64 GB' = "CPC_E_2C_4GB_64GB" 'Windows 365 Enterprise 2 vCPU 8 GB 128 GB' = "CPC_E_2C_8GB_128GB" 'Windows 365 Enterprise 2 vCPU 8 GB 128 GB (Preview)' = "CPC_LVL_2" 'Windows 365 Enterprise 2 vCPU 8 GB 256 GB' = "CPC_E_2C_8GB_256GB" 'Windows 365 Enterprise 4 vCPU 16 GB 128 GB' = "CPC_E_4C_16GB_128GB" 'Windows 365 Enterprise 4 vCPU 16 GB 256 GB' = "CPC_E_4C_16GB_256GB" 'Windows 365 Enterprise 4 vCPU 16 GB 256 GB (Preview)' = "CPC_LVL_3" 'Windows 365 Enterprise 4 vCPU 16 GB 512 GB' = "CPC_E_4C_16GB_512GB" 'Windows 365 Enterprise 8 vCPU 32 GB 128 GB' = "CPC_E_8C_32GB_128GB" 'Windows 365 Enterprise 8 vCPU 32 GB 256 GB' = "CPC_E_8C_32GB_256GB" 'Windows 365 Enterprise 8 vCPU 32 GB 512 GB' = "CPC_E_8C_32GB_512GB" 'Windows 365 Shared Use 2 vCPU 4 GB 128 GB' = "Windows_365_S_2vCPU_4GB_128GB" 'Windows 365 Shared Use 2 vCPU 4 GB 256 GB' = "Windows_365_S_2vCPU_4GB_256GB" 'Windows 365 Shared Use 2 vCPU 4 GB 64 GB' = "Windows_365_S_2vCPU_4GB_64GB" 'Windows 365 Shared Use 2 vCPU 8 GB 128 GB' = "Windows_365_S_2vCPU_8GB_128GB" 'Windows 365 Shared Use 2 vCPU 8 GB 256 GB' = "Windows_365_S_2vCPU_8GB_256GB" 'Windows 365 Shared Use 4 vCPU 16 GB 128 GB' = "Windows_365_S_4vCPU_16GB_128GB" 'Windows 365 Shared Use 4 vCPU 16 GB 256 GB' = "Windows_365_S_4vCPU_16GB_256GB" 'Windows 365 Shared Use 4 vCPU 16 GB 512 GB' = "Windows_365_S_4vCPU_16GB_512GB" 'Windows 365 Shared Use 8 vCPU 32 GB 128 GB' = "Windows_365_S_8vCPU_32GB_128GB" 'Windows 365 Shared Use 8 vCPU 32 GB 256 GB' = "Windows_365_S_8vCPU_32GB_256GB" 'Windows 365 Shared Use 8 vCPU 32 GB 512 GB' = "Windows_365_S_8vCPU_32GB_512GB" 'Windows Autopatch' = "Windows_Autopatch" 'Windows Store for Business' = "WINDOWS_STORE" 'Windows Store for Business EDU Faculty' = "WSFB_EDU_FACULTY" 'Windows Store for Business EDU Store_faculty' = "Windows Store for Business EDU Store_faculty" 'Windows Store Service' = "WINDOWS_STORE" 'Windows Update for Business Deployment Service' = "WINDOWSUPDATEFORBUSINESS_DEPLOYMENTSERVICE" 'YAMMER ENTERPRIS' = "YAMMER_ENTERPRISE" 'Yammer Enterprise' = "YAMMER_ENTERPRISE" 'Yammer for Academic' = "YAMMER_EDU" 'YAMMER MIDSIZE' = "YAMMER_MIDSIZE" 'YAMMER_ENTERPRISE' = "YAMMER_ENTERPRISE" 'YAMMER_MIDSIZE' = "YAMMER_MIDSIZE" } } Process { if (-not $ToSku) { $ConvertedLicenses = foreach ($LicenseToProcess in $License) { if ($LicenseToProcess -is [string]) { $L = $LicenseToProcess } elseif ($LicenseToProcess -is [Microsoft.Online.Administration.UserLicense]) { $L = $LicenseToProcess.AccountSkuId } else { continue } $L = $L -replace '.*(:)' $Conversion = $O365SKU[$L] if ($null -eq $Conversion) { $L } else { $Conversion } } } else { $ConvertedLicenses = :Outer foreach ($L in $License) { $Conversion = $SKUO365[$L] if ($null -eq $Conversion) { $L } else { $Conversion } } } if ($ReturnArray) { $ConvertedLicenses } else { $ConvertedLicenses -join $Separator } } End { } } function ConvertFrom-DistinguishedName { <# .SYNOPSIS Converts a Distinguished Name to CN, OU, Multiple OUs or DC .DESCRIPTION Converts a Distinguished Name to CN, OU, Multiple OUs or DC .PARAMETER DistinguishedName Distinguished Name to convert .PARAMETER ToOrganizationalUnit Converts DistinguishedName to Organizational Unit .PARAMETER ToDC Converts DistinguishedName to DC .PARAMETER ToDomainCN Converts DistinguishedName to Domain Canonical Name (CN) .PARAMETER ToCanonicalName Converts DistinguishedName to Canonical Name .EXAMPLE $DistinguishedName = 'CN=Przemyslaw Klys,OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz' ConvertFrom-DistinguishedName -DistinguishedName $DistinguishedName -ToOrganizationalUnit Output: OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz .EXAMPLE $DistinguishedName = 'CN=Przemyslaw Klys,OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz' ConvertFrom-DistinguishedName -DistinguishedName $DistinguishedName Output: Przemyslaw Klys .EXAMPLE ConvertFrom-DistinguishedName -DistinguishedName 'OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz' -ToMultipleOrganizationalUnit -IncludeParent Output: OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz OU=Production,DC=ad,DC=evotec,DC=xyz .EXAMPLE ConvertFrom-DistinguishedName -DistinguishedName 'OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz' -ToMultipleOrganizationalUnit Output: OU=Production,DC=ad,DC=evotec,DC=xyz .EXAMPLE $Con = @( 'CN=Windows Authorization Access Group,CN=Builtin,DC=ad,DC=evotec,DC=xyz' 'CN=Mmm,DC=elo,CN=nee,DC=RootDNSServers,CN=MicrosoftDNS,CN=System,DC=ad,DC=evotec,DC=xyz' 'CN=e6d5fd00-385d-4e65-b02d-9da3493ed850,CN=Operations,CN=DomainUpdates,CN=System,DC=ad,DC=evotec,DC=xyz' 'OU=Domain Controllers,DC=ad,DC=evotec,DC=pl' 'OU=Microsoft Exchange Security Groups,DC=ad,DC=evotec,DC=xyz' ) ConvertFrom-DistinguishedName -DistinguishedName $Con -ToLastName Output: Windows Authorization Access Group Mmm e6d5fd00-385d-4e65-b02d-9da3493ed850 Domain Controllers Microsoft Exchange Security Groups .EXAMPLEE ConvertFrom-DistinguishedName -DistinguishedName 'DC=ad,DC=evotec,DC=xyz' -ToCanonicalName ConvertFrom-DistinguishedName -DistinguishedName 'OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz' -ToCanonicalName ConvertFrom-DistinguishedName -DistinguishedName 'CN=test,OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz' -ToCanonicalName Output: ad.evotec.xyz ad.evotec.xyz\Production\Users ad.evotec.xyz\Production\Users\test .NOTES General notes #> [CmdletBinding(DefaultParameterSetName = 'Default')] param( [Parameter(ParameterSetName = 'ToOrganizationalUnit')] [Parameter(ParameterSetName = 'ToMultipleOrganizationalUnit')] [Parameter(ParameterSetName = 'ToDC')] [Parameter(ParameterSetName = 'ToDomainCN')] [Parameter(ParameterSetName = 'Default')] [Parameter(ParameterSetName = 'ToLastName')] [Parameter(ParameterSetName = 'ToCanonicalName')] [alias('Identity', 'DN')][Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName, Position = 0)][string[]] $DistinguishedName, [Parameter(ParameterSetName = 'ToOrganizationalUnit')][switch] $ToOrganizationalUnit, [Parameter(ParameterSetName = 'ToMultipleOrganizationalUnit')][alias('ToMultipleOU')][switch] $ToMultipleOrganizationalUnit, [Parameter(ParameterSetName = 'ToMultipleOrganizationalUnit')][switch] $IncludeParent, [Parameter(ParameterSetName = 'ToDC')][switch] $ToDC, [Parameter(ParameterSetName = 'ToDomainCN')][switch] $ToDomainCN, [Parameter(ParameterSetName = 'ToLastName')][switch] $ToLastName, [Parameter(ParameterSetName = 'ToCanonicalName')][switch] $ToCanonicalName ) Process { foreach ($Distinguished in $DistinguishedName) { if ($ToDomainCN) { $DN = $Distinguished -replace '.*?((DC=[^=]+,)+DC=[^=]+)$', '$1' $CN = $DN -replace ',DC=', '.' -replace "DC=" if ($CN) { $CN } } elseif ($ToOrganizationalUnit) { $Value = [Regex]::Match($Distinguished, '(?=OU=)(.*\n?)(?<=.)').Value if ($Value) { $Value } } elseif ($ToMultipleOrganizationalUnit) { if ($IncludeParent) { $Distinguished } while ($true) { $Distinguished = $Distinguished -replace '^.+?,(?=..=)' if ($Distinguished -match '^DC=') { break } $Distinguished } } elseif ($ToDC) { $Value = $Distinguished -replace '.*?((DC=[^=]+,)+DC=[^=]+)$', '$1' if ($Value) { $Value } } elseif ($ToLastName) { $NewDN = $Distinguished -split ",DC=" if ($NewDN[0].Contains(",OU=")) { [Array] $ChangedDN = $NewDN[0] -split ",OU=" } elseif ($NewDN[0].Contains(",CN=")) { [Array] $ChangedDN = $NewDN[0] -split ",CN=" } else { [Array] $ChangedDN = $NewDN[0] } if ($ChangedDN[0].StartsWith('CN=')) { $ChangedDN[0] -replace 'CN=', '' } else { $ChangedDN[0] -replace 'OU=', '' } } elseif ($ToCanonicalName) { $Domain = $null $Rest = $null foreach ($O in $Distinguished -split '(?<!\\),') { if ($O -match '^DC=') { $Domain += $O.Substring(3) + '.' } else { $Rest = $O.Substring(3) + '\' + $Rest } } if ($Domain -and $Rest) { $Domain.Trim('.') + '\' + ($Rest.TrimEnd('\') -replace '\\,', ',') } elseif ($Domain) { $Domain.Trim('.') } elseif ($Rest) { $Rest.TrimEnd('\') -replace '\\,', ',' } } else { $Regex = '^CN=(?<cn>.+?)(?<!\\),(?<ou>(?:(?:OU|CN).+?(?<!\\),)+(?<dc>DC.+?))$' $Found = $Distinguished -match $Regex if ($Found) { $Matches.cn } } } } } function Copy-Dictionary { <# .SYNOPSIS Copies dictionary/hashtable .DESCRIPTION Copies dictionary uusing PS Serializer. Replaces usage of BinnaryFormatter due to no support in PS 7.4 .PARAMETER Dictionary Dictionary to copy .EXAMPLE $Test = [ordered] @{ Test = 'Test' Test1 = @{ Test2 = 'Test2' Test3 = @{ Test4 = 'Test4' } } Test2 = @( "1", "2", "3" ) Test3 = [PSCustomObject] @{ Test4 = 'Test4' Test5 = 'Test5' } } $New1 = Copy-Dictionary -Dictionary $Test $New1 .NOTES #> [alias('Copy-Hashtable', 'Copy-OrderedHashtable')] [cmdletbinding()] param( [System.Collections.IDictionary] $Dictionary ) $clone = [System.Management.Automation.PSSerializer]::Serialize($Dictionary, [int32]::MaxValue) return [System.Management.Automation.PSSerializer]::Deserialize($clone) } function Format-StringToSentence { <# .SYNOPSIS Formats a given string by adding spaces before uppercase letters, digits, and non-word characters. .DESCRIPTION The Format-AddSpaceToSentence function takes a string or an array of strings and adds a space before each uppercase letter, digit, and non-word character (excluding dots, spaces, and underscores). It also provides options to convert the string to lowercase, remove certain characters before or after the formatting, and remove double spaces. .PARAMETER Text The string or array of strings to be formatted. .PARAMETER RemoveCharsBefore An array of characters to be removed from the string before the formatting is applied. .PARAMETER RemoveCharsAfter An array of characters to be removed from the string after the formatting is applied. .PARAMETER ToLowerCase If this switch is present, the function will convert the string to lowercase. .PARAMETER RemoveDoubleSpaces If this switch is present, the function will remove any double spaces from the string. .PARAMETER MakeWordsUpperCase An array of words that should be converted to uppercase after the formatting is applied. .PARAMETER DisableAddingSpace If this switch is present, the function will not add spaces before uppercase letters, digits, and non-word characters. .EXAMPLE $test = @( 'OnceUponATime', 'OnceUponATime1', 'Money@Risk', 'OnceUponATime123', 'AHappyMan2014' 'OnceUponATime_123' 'Domain test.com' ) Format-StringToSentence -Text $Test -RemoveCharsAfter '_' -RemoveDoubleSpaces This example formats each string in the $test array, removes any underscores after the formatting, and removes any double spaces. .EXAMPLE $test = @( 'OnceUponATime', 'OnceUponATime1', 'Money@Risk', 'OnceUponATime123', 'AHappyMan2014' 'OnceUponATime_123' 'Domain test.com' ) $Test | Format-StringToSentence -ToLowerCase -RemoveCharsAfter '_' -RemoveDoubleSpaces This example does the same as the previous one, but also converts each string to lowercase. .EXAMPLE $test = @( 'OnceUponATime', 'OnceUponATime1', 'Money@Risk', 'OnceUponATime123', 'AHappyMan2014' 'OnceUponATime_123' 'Domain test.com' ) Format-StringToSentence -Text $Test -RemoveCharsAfter '_' -RemoveDoubleSpaces -MakeWordsUpperCase 'test.com', 'money' .NOTES The function uses the -creplace operator to add spaces, which is case-insensitive. Therefore, it will add spaces before both uppercase and lowercase letters if they are specified in the RemoveCharsBefore or RemoveCharsAfter parameters. #> [alias('Format-AddSpaceToSentence')] [CmdletBinding()] param( [Parameter(Mandatory = $false, ValueFromPipeline = $true, Position = 0)][string[]] $Text, [string[]] $RemoveCharsBefore, [string[]] $RemoveCharsAfter, [switch] $ToLowerCase, [switch] $RemoveDoubleSpaces, [string[]] $MakeWordsUpperCase, [switch] $DisableAddingSpace ) Process { foreach ($T in $Text) { if ($RemoveCharsBefore) { foreach ($R in $RemoveCharsBefore) { $T = $T -ireplace [regex]::Escape($R), "" } } if (-not $DisableAddingSpace) { $T = $T -creplace '([A-Z]|[^a-zA-Z0-9_.\s]|_|\d+)(?<![a-z])', ' $&' } if ($ToLowerCase) { $T = $T.ToLower() } if ($RemoveCharsAfter) { foreach ($R in $RemoveCharsAfter) { $T = $T -ireplace [regex]::Escape($R), "" } } if ($RemoveDoubleSpaces) { $T = $T -creplace '\s+', ' ' } if ($MakeWordsUpperCase) { foreach ($W in $MakeWordsUpperCase) { $T = $T -ireplace [regex]::Escape($W), $W.ToUpper() } } $T.Trim() } } } function Get-FileName { <# .SYNOPSIS Generates a temporary file name with the specified extension. .DESCRIPTION This function generates a temporary file name based on the provided extension. It can generate a temporary file name in the system's temporary folder or just the file name itself. .PARAMETER Extension Specifies the extension for the temporary file name. Default is 'tmp'. .PARAMETER Temporary Indicates whether to generate a temporary file name in the system's temporary folder. .PARAMETER TemporaryFileOnly Indicates whether to generate only the temporary file name without the path. .EXAMPLE Get-FileName -Temporary Generates a temporary file name in the system's temporary folder. Example output: 3ymsxvav.tmp .EXAMPLE Get-FileName -Temporary Generates a temporary file name without the path. Example output: tmpD74C.tmp .EXAMPLE Get-FileName -Temporary -Extension 'xlsx' Generates a temporary file name with the specified extension in the system's temporary folder. Example output: tmp45B6.xlsx .NOTES These examples demonstrate how to use the Get-FileName function to generate temporary file names. #> [CmdletBinding()] param( [string] $Extension = 'tmp', [switch] $Temporary, [switch] $TemporaryFileOnly ) if ($Temporary) { return [io.path]::Combine([System.IO.Path]::GetTempPath(), "$($([System.IO.Path]::GetRandomFileName()).Split('.')[0]).$Extension") } if ($TemporaryFileOnly) { return "$($([System.IO.Path]::GetRandomFileName()).Split('.')[0]).$Extension" } } function Get-GitHubLatestRelease { <# .SYNOPSIS Gets one or more releases from GitHub repository .DESCRIPTION Gets one or more releases from GitHub repository .PARAMETER Url Url to github repository .EXAMPLE Get-GitHubLatestRelease -Url "https://api.github.com/repos/evotecit/Testimo/releases" | Format-Table .NOTES General notes #> [CmdLetBinding()] param( [parameter(Mandatory)][alias('ReleasesUrl')][uri] $Url ) $ProgressPreference = 'SilentlyContinue' $Responds = Test-Connection -ComputerName $URl.Host -Quiet -Count 1 if ($Responds) { Try { [Array] $JsonOutput = (Invoke-WebRequest -Uri $Url -ErrorAction Stop | ConvertFrom-Json) foreach ($JsonContent in $JsonOutput) { [PSCustomObject] @{ PublishDate = [DateTime] $JsonContent.published_at CreatedDate = [DateTime] $JsonContent.created_at PreRelease = [bool] $JsonContent.prerelease Version = [version] ($JsonContent.name -replace 'v', '') Tag = $JsonContent.tag_name Branch = $JsonContent.target_commitish Errors = '' } } } catch { [PSCustomObject] @{ PublishDate = $null CreatedDate = $null PreRelease = $null Version = $null Tag = $null Branch = $null Errors = $_.Exception.Message } } } else { [PSCustomObject] @{ PublishDate = $null CreatedDate = $null PreRelease = $null Version = $null Tag = $null Branch = $null Errors = "No connection (ping) to $($Url.Host)" } } $ProgressPreference = 'Continue' } function Get-O365TenantID { <# .SYNOPSIS Quick way to find Office 365 Tenant ID by using domain name .DESCRIPTION Quick way to find Office 365 Tenant ID by using domain name .PARAMETER Domain Domain name to check .EXAMPLE Get-O365TenantID -Domain 'evotec.pl' .NOTES General notes #> [cmdletbinding()] param( [parameter(Mandatory)][alias('DomainName')][string] $Domain ) $Invoke = Invoke-RestMethod "https://login.windows.net/$Domain/.well-known/openid-configuration" -Method GET -Verbose:$false if ($Invoke) { $Invoke.userinfo_endpoint.Split("/")[3] } } function Remove-EmptyValue { [alias('Remove-EmptyValues')] [CmdletBinding()] param( [alias('Splat', 'IDictionary')][Parameter(Mandatory)][System.Collections.IDictionary] $Hashtable, [string[]] $ExcludeParameter, [switch] $Recursive, [int] $Rerun, [switch] $DoNotRemoveNull, [switch] $DoNotRemoveEmpty, [switch] $DoNotRemoveEmptyArray, [switch] $DoNotRemoveEmptyDictionary ) foreach ($Key in [string[]] $Hashtable.Keys) { if ($Key -notin $ExcludeParameter) { if ($Recursive) { if ($Hashtable[$Key] -is [System.Collections.IDictionary]) { if ($Hashtable[$Key].Count -eq 0) { if (-not $DoNotRemoveEmptyDictionary) { $Hashtable.Remove($Key) } } else { Remove-EmptyValue -Hashtable $Hashtable[$Key] -Recursive:$Recursive } } else { if (-not $DoNotRemoveNull -and $null -eq $Hashtable[$Key]) { $Hashtable.Remove($Key) } elseif (-not $DoNotRemoveEmpty -and $Hashtable[$Key] -is [string] -and $Hashtable[$Key] -eq '') { $Hashtable.Remove($Key) } elseif (-not $DoNotRemoveEmptyArray -and $Hashtable[$Key] -is [System.Collections.IList] -and $Hashtable[$Key].Count -eq 0) { $Hashtable.Remove($Key) } } } else { if (-not $DoNotRemoveNull -and $null -eq $Hashtable[$Key]) { $Hashtable.Remove($Key) } elseif (-not $DoNotRemoveEmpty -and $Hashtable[$Key] -is [string] -and $Hashtable[$Key] -eq '') { $Hashtable.Remove($Key) } elseif (-not $DoNotRemoveEmptyArray -and $Hashtable[$Key] -is [System.Collections.IList] -and $Hashtable[$Key].Count -eq 0) { $Hashtable.Remove($Key) } } } } if ($Rerun) { for ($i = 0; $i -lt $Rerun; $i++) { Remove-EmptyValue -Hashtable $Hashtable -Recursive:$Recursive } } } function Start-TimeLog { <# .SYNOPSIS Starts a new stopwatch for logging time. .DESCRIPTION This function starts a new stopwatch that can be used for logging time durations. .EXAMPLE Start-TimeLog Starts a new stopwatch for logging time. #> [CmdletBinding()] param() [System.Diagnostics.Stopwatch]::StartNew() } function Stop-TimeLog { <# .SYNOPSIS Stops the stopwatch and returns the elapsed time in a specified format. .DESCRIPTION The Stop-TimeLog function stops the provided stopwatch and returns the elapsed time in a specified format. The function can output the elapsed time as a single string or an array of days, hours, minutes, seconds, and milliseconds. .PARAMETER Time Specifies the stopwatch object to stop and retrieve the elapsed time from. .PARAMETER Option Specifies the format in which the elapsed time should be returned. Valid values are 'OneLiner' (default) or 'Array'. .PARAMETER Continue Indicates whether the stopwatch should continue running after retrieving the elapsed time. .EXAMPLE $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() # Perform some operations Stop-TimeLog -Time $stopwatch # Output: "0 days, 0 hours, 0 minutes, 5 seconds, 123 milliseconds" .EXAMPLE $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() # Perform some operations Stop-TimeLog -Time $stopwatch -Option Array # Output: ["0 days", "0 hours", "0 minutes", "5 seconds", "123 milliseconds"] #> [CmdletBinding()] param ( [Parameter(ValueFromPipeline = $true)][System.Diagnostics.Stopwatch] $Time, [ValidateSet('OneLiner', 'Array')][string] $Option = 'OneLiner', [switch] $Continue ) Begin { } Process { if ($Option -eq 'Array') { $TimeToExecute = "$($Time.Elapsed.Days) days", "$($Time.Elapsed.Hours) hours", "$($Time.Elapsed.Minutes) minutes", "$($Time.Elapsed.Seconds) seconds", "$($Time.Elapsed.Milliseconds) milliseconds" } else { $TimeToExecute = "$($Time.Elapsed.Days) days, $($Time.Elapsed.Hours) hours, $($Time.Elapsed.Minutes) minutes, $($Time.Elapsed.Seconds) seconds, $($Time.Elapsed.Milliseconds) milliseconds" } } End { if (-not $Continue) { $Time.Stop() } return $TimeToExecute } } function Write-Color { <# .SYNOPSIS Write-Color is a wrapper around Write-Host delivering a lot of additional features for easier color options. .DESCRIPTION Write-Color is a wrapper around Write-Host delivering a lot of additional features for easier color options. It provides: - Easy manipulation of colors, - Logging output to file (log) - Nice formatting options out of the box. - Ability to use aliases for parameters .PARAMETER Text Text to display on screen and write to log file if specified. Accepts an array of strings. .PARAMETER Color Color of the text. Accepts an array of colors. If more than one color is specified it will loop through colors for each string. If there are more strings than colors it will start from the beginning. Available colors are: Black, DarkBlue, DarkGreen, DarkCyan, DarkRed, DarkMagenta, DarkYellow, Gray, DarkGray, Blue, Green, Cyan, Red, Magenta, Yellow, White .PARAMETER BackGroundColor Color of the background. Accepts an array of colors. If more than one color is specified it will loop through colors for each string. If there are more strings than colors it will start from the beginning. Available colors are: Black, DarkBlue, DarkGreen, DarkCyan, DarkRed, DarkMagenta, DarkYellow, Gray, DarkGray, Blue, Green, Cyan, Red, Magenta, Yellow, White .PARAMETER StartTab Number of tabs to add before text. Default is 0. .PARAMETER LinesBefore Number of empty lines before text. Default is 0. .PARAMETER LinesAfter Number of empty lines after text. Default is 0. .PARAMETER StartSpaces Number of spaces to add before text. Default is 0. .PARAMETER LogFile Path to log file. If not specified no log file will be created. .PARAMETER DateTimeFormat Custom date and time format string. Default is yyyy-MM-dd HH:mm:ss .PARAMETER LogTime If set to $true it will add time to log file. Default is $true. .PARAMETER LogRetry Number of retries to write to log file, in case it can't write to it for some reason, before skipping. Default is 2. .PARAMETER Encoding Encoding of the log file. Default is Unicode. .PARAMETER ShowTime Switch to add time to console output. Default is not set. .PARAMETER NoNewLine Switch to not add new line at the end of the output. Default is not set. .PARAMETER NoConsoleOutput Switch to not output to console. Default all output goes to console. .EXAMPLE Write-Color -Text "Red ", "Green ", "Yellow " -Color Red,Green,Yellow .EXAMPLE Write-Color -Text "This is text in Green ", "followed by red ", "and then we have Magenta... ", "isn't it fun? ", "Here goes DarkCyan" -Color Green,Red,Magenta,White,DarkCyan .EXAMPLE Write-Color -Text "This is text in Green ", "followed by red ", "and then we have Magenta... ", "isn't it fun? ", "Here goes DarkCyan" -Color Green,Red,Magenta,White,DarkCyan -StartTab 3 -LinesBefore 1 -LinesAfter 1 .EXAMPLE Write-Color "1. ", "Option 1" -Color Yellow, Green Write-Color "2. ", "Option 2" -Color Yellow, Green Write-Color "3. ", "Option 3" -Color Yellow, Green Write-Color "4. ", "Option 4" -Color Yellow, Green Write-Color "9. ", "Press 9 to exit" -Color Yellow, Gray -LinesBefore 1 .EXAMPLE Write-Color -LinesBefore 2 -Text "This little ","message is ", "written to log ", "file as well." ` -Color Yellow, White, Green, Red, Red -LogFile "C:\testing.txt" -TimeFormat "yyyy-MM-dd HH:mm:ss" Write-Color -Text "This can get ","handy if ", "want to display things, and log actions to file ", "at the same time." ` -Color Yellow, White, Green, Red, Red -LogFile "C:\testing.txt" .EXAMPLE Write-Color -T "My text", " is ", "all colorful" -C Yellow, Red, Green -B Green, Green, Yellow Write-Color -t "my text" -c yellow -b green Write-Color -text "my text" -c red .EXAMPLE Write-Color -Text "Testuję czy się ładnie zapisze, czy będą problemy" -Encoding unicode -LogFile 'C:\temp\testinggg.txt' -Color Red -NoConsoleOutput .NOTES Understanding Custom date and time format strings: https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings Project support: https://github.com/EvotecIT/PSWriteColor Original idea: Josh (https://stackoverflow.com/users/81769/josh) #> [alias('Write-Colour')] [CmdletBinding()] param ( [alias ('T')] [String[]]$Text, [alias ('C', 'ForegroundColor', 'FGC')] [ConsoleColor[]]$Color = [ConsoleColor]::White, [alias ('B', 'BGC')] [ConsoleColor[]]$BackGroundColor = $null, [alias ('Indent')][int] $StartTab = 0, [int] $LinesBefore = 0, [int] $LinesAfter = 0, [int] $StartSpaces = 0, [alias ('L')] [string] $LogFile = '', [Alias('DateFormat', 'TimeFormat')][string] $DateTimeFormat = 'yyyy-MM-dd HH:mm:ss', [alias ('LogTimeStamp')][bool] $LogTime = $true, [int] $LogRetry = 2, [ValidateSet('unknown', 'string', 'unicode', 'bigendianunicode', 'utf8', 'utf7', 'utf32', 'ascii', 'default', 'oem')][string]$Encoding = 'Unicode', [switch] $ShowTime, [switch] $NoNewLine, [alias('HideConsole')][switch] $NoConsoleOutput ) if (-not $NoConsoleOutput) { $DefaultColor = $Color[0] if ($null -ne $BackGroundColor -and $BackGroundColor.Count -ne $Color.Count) { Write-Error "Colors, BackGroundColors parameters count doesn't match. Terminated." return } if ($LinesBefore -ne 0) { for ($i = 0; $i -lt $LinesBefore; $i++) { Write-Host -Object "`n" -NoNewline } } # Add empty line before if ($StartTab -ne 0) { for ($i = 0; $i -lt $StartTab; $i++) { Write-Host -Object "`t" -NoNewline } } # Add TABS before text if ($StartSpaces -ne 0) { for ($i = 0; $i -lt $StartSpaces; $i++) { Write-Host -Object ' ' -NoNewline } } # Add SPACES before text if ($ShowTime) { Write-Host -Object "[$([datetime]::Now.ToString($DateTimeFormat))] " -NoNewline } # Add Time before output if ($Text.Count -ne 0) { if ($Color.Count -ge $Text.Count) { # the real deal coloring if ($null -eq $BackGroundColor) { for ($i = 0; $i -lt $Text.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $Color[$i] -NoNewline } } else { for ($i = 0; $i -lt $Text.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $Color[$i] -BackgroundColor $BackGroundColor[$i] -NoNewline } } } else { if ($null -eq $BackGroundColor) { for ($i = 0; $i -lt $Color.Length ; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $Color[$i] -NoNewline } for ($i = $Color.Length; $i -lt $Text.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $DefaultColor -NoNewline } } else { for ($i = 0; $i -lt $Color.Length ; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $Color[$i] -BackgroundColor $BackGroundColor[$i] -NoNewline } for ($i = $Color.Length; $i -lt $Text.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $DefaultColor -BackgroundColor $BackGroundColor[0] -NoNewline } } } } if ($NoNewLine -eq $true) { Write-Host -NoNewline } else { Write-Host } # Support for no new line if ($LinesAfter -ne 0) { for ($i = 0; $i -lt $LinesAfter; $i++) { Write-Host -Object "`n" -NoNewline } } # Add empty line after } if ($Text.Count -and $LogFile) { # Save to file $TextToFile = "" for ($i = 0; $i -lt $Text.Length; $i++) { $TextToFile += $Text[$i] } $Saved = $false $Retry = 0 Do { $Retry++ try { if ($LogTime) { "[$([datetime]::Now.ToString($DateTimeFormat))] $TextToFile" | Out-File -FilePath $LogFile -Encoding $Encoding -Append -ErrorAction Stop -WhatIf:$false } else { "$TextToFile" | Out-File -FilePath $LogFile -Encoding $Encoding -Append -ErrorAction Stop -WhatIf:$false } $Saved = $true } catch { if ($Saved -eq $false -and $Retry -eq $LogRetry) { Write-Warning "Write-Color - Couldn't write to log file $($_.Exception.Message). Tried ($Retry/$LogRetry))" } else { Write-Warning "Write-Color - Couldn't write to log file $($_.Exception.Message). Retrying... ($Retry/$LogRetry)" } } } Until ($Saved -eq $true -or $Retry -ge $LogRetry) } } $Script:Apps = [ordered] @{ Name = 'Azure Active Directory Apps' Enabled = $true Execute = { Get-MyApp } Processing = { } Summary = { } Variables = @{ } Solution = { if ($Script:Reporting['Apps']['Data']) { New-HTMLTable -DataTable $Script:Reporting['Apps']['Data'] -Filtering { New-HTMLTableCondition -Name 'DescriptionWithEmail' -Operator eq -Value $true -ComparisonType string -BackgroundColor SpringGreen -FailBackgroundColor Salmon New-HTMLTableCondition -Name 'KeysCount' -Operator gt -Value 1 -ComparisonType number -BackgroundColor GoldenFizz New-HTMLTableCondition -Name 'KeysCount' -Operator eq -Value 0 -ComparisonType number -BackgroundColor Salmon -Row New-HTMLTableCondition -Name 'KeysCount' -Operator eq -Value 1 -ComparisonType number -BackgroundColor SpringGreen New-HTMLTableCondition -Name 'Expired' -Operator eq -Value "No" -ComparisonType string -BackgroundColor SpringGreen New-HTMLTableCondition -Name 'Expired' -Operator eq -Value "Yes" -ComparisonType string -BackgroundColor Salmon -Row New-HTMLTableCondition -Name 'Expired' -Operator eq -Value "Not available" -ComparisonType string -BackgroundColor Salmon -Row } -ScrollX } } } $Script:AppsCredentials = [ordered] @{ Name = 'Azure Active Directory Apps Credentials' Enabled = $true Execute = { Get-MyAppCredentials } Processing = { } Summary = { } Variables = @{ } Solution = { if ($Script:Reporting['AppsCredentials']['Data']) { New-HTMLTable -DataTable $Script:Reporting['AppsCredentials']['Data'] -Filtering { New-HTMLTableCondition -Name 'Expired' -Operator eq -Value $false -ComparisonType string -BackgroundColor SpringGreen -FailBackgroundColor Salmon New-HTMLTableCondition -Name 'DaysToExpire' -Value 30 -Operator 'ge' -BackgroundColor Conifer -ComparisonType number New-HTMLTableCondition -Name 'DaysToExpire' -Value 30 -Operator 'lt' -BackgroundColor Orange -ComparisonType number New-HTMLTableCondition -Name 'DaysToExpire' -Value 5 -Operator 'lt' -BackgroundColor Red -ComparisonType number } -ScrollX } } } $Script:Licenses = [ordered] @{ Name = 'Azure Licenses' Enabled = $true Execute = { Get-MyLicense } Processing = { } Summary = { } Variables = @{ } Solution = { if ($Script:Reporting['Licenses']['Data']) { New-HTMLTable -DataTable $Script:Reporting['Licenses']['Data'] -Filtering { New-HTMLTableCondition -Name 'CapabilityStatus' -Operator eq -Value 'Enabled' -ComparisonType string -BackgroundColor LightGreen -FailBackgroundColor Orange New-HTMLTableCondition -Name 'LicensesUsedPercent' -Operator gt -Value 100 -ComparisonType number -BackgroundColor Alizarin -HighlightHeaders 'LicensesUsedCount', 'LicensesUsedPercent' New-HTMLTableCondition -Name 'LicensesUsedPercent' -Operator eq -Value 100 -ComparisonType number -BackgroundColor Salmon -HighlightHeaders 'LicensesUsedCount', 'LicensesUsedPercent' New-HTMLTableCondition -Name 'LicensesUsedPercent' -Operator betweenInclusive -Value 70, 99 -ComparisonType number -BackgroundColor Orange -HighlightHeaders 'LicensesUsedCount', 'LicensesUsedPercent' New-HTMLTableCondition -Name 'LicensesUsedPercent' -Operator betweenInclusive -Value 40, 69 -ComparisonType number -BackgroundColor LightSkyBlue -HighlightHeaders 'LicensesUsedCount', 'LicensesUsedPercent' New-HTMLTableCondition -Name 'LicensesUsedPercent' -Operator betweenInclusive -Value 1, 39 -ComparisonType number -BackgroundColor Almond -HighlightHeaders 'LicensesUsedCount', 'LicensesUsedPercent' New-HTMLTableCondition -Name 'LicensesUsedPercent' -Operator eq -Value 0 -ComparisonType number -BackgroundColor LightGreen -HighlightHeaders 'LicensesUsedCount', 'LicensesUsedPercent' } -ScrollX } } } $Script:Devices = [ordered] @{ Name = 'Azure Active Directory Devices' Enabled = $true Execute = { Get-MyDevice } Processing = { } Summary = { } Variables = @{ } Solution = { if ($Script:Reporting['Devices']['Data']) { New-HTMLTable -DataTable $Script:Reporting['Devices']['Data'] -Filtering { New-HTMLTableCondition -Name 'Enabled' -Value $true -Operator eq -ComparisonType string -BackgroundColor MediumSpringGreen New-HTMLTableCondition -Name 'Enabled' -Value $false -Operator eq -ComparisonType string -BackgroundColor Cinnabar New-HTMLTableCondition -Name 'IsManaged' -Value $true -Operator eq -ComparisonType string -BackgroundColor MediumSpringGreen New-HTMLTableCondition -Name 'IsManaged' -Value $false -Operator eq -ComparisonType string -BackgroundColor Cinnabar New-HTMLTableCondition -Name 'IsCompliant' -Value $true -Operator eq -ComparisonType string -BackgroundColor MediumSpringGreen New-HTMLTableCondition -Name 'IsCompliant' -Value $false -Operator eq -ComparisonType string -BackgroundColor Cinnabar New-HTMLTableCondition -Name 'IsSynchronized' -Value $true -Operator eq -ComparisonType string -BackgroundColor MediumSpringGreen New-HTMLTableCondition -Name 'IsSynchronized' -Value $false -Operator eq -ComparisonType string -BackgroundColor Cinnabar New-HTMLTableCondition -Name 'LastSeenDays' -Value 180 -Operator gt -ComparisonType number -BackgroundColor CoralRed -HighlightHeaders 'LastSeenDays', 'LastSeen' New-HTMLTableCondition -Name 'LastSeenDays' -Value 180 -Operator le -ComparisonType number -BackgroundColor SunsetOrange -HighlightHeaders 'LastSeenDays', 'LastSeen' New-HTMLTableCondition -Name 'LastSeenDays' -Value 90 -Operator le -ComparisonType number -BackgroundColor LaserLemon -HighlightHeaders 'LastSeenDays', 'LastSeen' New-HTMLTableCondition -Name 'LastSeenDays' -Value 30 -Operator le -ComparisonType number -BackgroundColor MediumSpringGreen -HighlightHeaders 'LastSeenDays', 'LastSeen' New-HTMLTableCondition -Name 'LastSynchronizedDays' -Value 180 -Operator gt -ComparisonType number -BackgroundColor CoralRed -HighlightHeaders 'LastSynchronizedDays', 'LastSynchronized' New-HTMLTableCondition -Name 'LastSynchronizedDays' -Value 180 -Operator le -ComparisonType number -BackgroundColor SunsetOrange -HighlightHeaders 'LastSynchronizedDays', 'LastSynchronized' New-HTMLTableCondition -Name 'LastSynchronizedDays' -Value 90 -Operator le -ComparisonType number -BackgroundColor LaserLemon -HighlightHeaders 'LastSynchronizedDays', 'LastSynchronized' New-HTMLTableCondition -Name 'LastSynchronizedDays' -Value 30 -Operator le -ComparisonType number -BackgroundColor MediumSpringGreen -HighlightHeaders 'LastSynchronizedDays', 'LastSynchronized' New-HTMLTableCondition -Name 'OwnerEnabled' -ComparisonType string -Operator eq -Value $true -BackgroundColor MediumSpringGreen New-HTMLTableCondition -Name 'OwnerEnabled' -ComparisonType string -Operator eq -Value $false -BackgroundColor Cinnabar } -ScrollX } } } $Script:DevicesIntune = [ordered] @{ Name = 'Azure Active Directory Devices Intune' Enabled = $true Execute = { Get-MyDeviceIntune } Processing = { } Summary = { } Variables = @{ } Solution = { if ($Script:Reporting['DevicesIntune']['Data']) { New-HTMLTable -DataTable $Script:Reporting['DevicesIntune']['Data'] -Filtering { New-HTMLTableCondition -Name 'ComplianceState' -Operator eq -Value 'Compliant' -ComparisonType string -BackgroundColor MediumSpringGreen -FailBackgroundColor Cinnabar New-HTMLTableCondition -Name 'LastSeenDays' -Value 180 -Operator gt -ComparisonType number -BackgroundColor CoralRed -HighlightHeaders 'LastSeenDays', 'LastSeen' New-HTMLTableCondition -Name 'LastSeenDays' -Value 180 -Operator le -ComparisonType number -BackgroundColor SunsetOrange -HighlightHeaders 'LastSeenDays', 'LastSeen' New-HTMLTableCondition -Name 'LastSeenDays' -Value 90 -Operator le -ComparisonType number -BackgroundColor LaserLemon -HighlightHeaders 'LastSeenDays', 'LastSeen' New-HTMLTableCondition -Name 'LastSeenDays' -Value 30 -Operator le -ComparisonType number -BackgroundColor MediumSpringGreen -HighlightHeaders 'LastSeenDays', 'LastSeen' } -ScrollX } } } $Script:Roles = [ordered] @{ Name = 'Azure Active Directory Roles' Enabled = $true Execute = { Get-MyRole -OnlyWithMembers } Processing = { } Summary = { } Variables = @{ } Solution = { if ($Script:Reporting['Roles']['Data']) { New-HTMLTable -DataTable $Script:Reporting['Roles']['Data'] -Filtering { New-HTMLTableCondition -Name 'IsEnabled' -Operator eq -Value $true -ComparisonType string -BackgroundColor SpringGreen -FailBackgroundColor Salmon } -ScrollX } } } $Script:RolesUsers = [ordered] @{ Name = 'Azure Active Directory Roles Users' Enabled = $true Execute = { Get-MyRoleUsers -OnlyWithRoles } Processing = { } Summary = { } Variables = @{ } Solution = { if ($Script:Reporting['RolesUsers']['Data']) { New-HTMLTable -DataTable $Script:Reporting['RolesUsers']['Data'] -Filtering { New-HTMLTableCondition -Name 'Enabled' -Operator eq -Value $true -ComparisonType string -BackgroundColor SpringGreen New-HTMLTableCondition -Name 'Enabled' -Operator eq -Value $false -ComparisonType string -BackgroundColor Salmon New-HTMLTableCondition -Name 'Status' -Operator eq -Value 'Synchronized' -ComparisonType string -BackgroundColor SpringGreen New-HTMLTableCondition -Name 'Status' -Operator eq -Value 'Online' -ComparisonType string -BackgroundColor GoldenFizz } -ScrollX } } } $Script:RolesUsersPerColumn = [ordered] @{ Name = 'Azure Active Directory Roles Users Per Column' Enabled = $true Execute = { Get-MyRoleUsers -OnlyWithRoles -RolePerColumn } Processing = { } Summary = { } Variables = @{ } Solution = { if ($Script:Reporting['RolesUsersPerColumn']['Data']) { New-HTMLTable -DataTable $Script:Reporting['RolesUsersPerColumn']['Data'] -Filtering { New-HTMLTableCondition -Name 'Enabled' -Operator eq -Value $true -ComparisonType string -BackgroundColor SpringGreen New-HTMLTableCondition -Name 'Enabled' -Operator eq -Value $false -ComparisonType string -BackgroundColor Salmon foreach ($Name in $Script:Reporting['RolesUsersPerColumn']['Data'][0].PSObject.Properties.Name) { if ($Name -notin 'Name', 'Enabled', 'UserPrincipalName', 'Mail' , 'Status', 'Type', 'Location', 'CreatedDateTime') { New-HTMLTableCondition -Name $Name -Operator eq -Value 'Direct' -ComparisonType string -BackgroundColor GoldenFizz New-HTMLTableCondition -Name $Name -Operator eq -Value 'Eligible' -ComparisonType string -BackgroundColor SpringGreen New-HTMLTableConditionGroup -Conditions { New-HTMLTableCondition -Name $Name -Operator ne -Value 'Eligible' -ComparisonType string New-HTMLTableCondition -Name $Name -Operator ne -Value 'Direct' -ComparisonType string New-HTMLTableCondition -Name $Name -Operator ne -Value '' -ComparisonType string } -Logic AND -BackgroundColor Orange -HighlightHeaders $Name } } New-HTMLTableCondition -Name 'Status' -Operator eq -Value 'Synchronized' -ComparisonType string -BackgroundColor SpringGreen New-HTMLTableCondition -Name 'Status' -Operator eq -Value 'Online' -ComparisonType string -BackgroundColor GoldenFizz } -ScrollX } } } $Script:Teams = [ordered] @{ Name = 'Microsoft Teams Report' Enabled = $true Execute = { Get-MyTeam } Processing = { } Summary = { } Variables = @{ } Solution = { if ($Script:Reporting['Teams']['Data']) { New-HTMLTable -DataTable $Script:Reporting['Teams']['Data'] -Filtering { } -ScrollX } } } $Script:Users = [ordered] @{ Name = 'Azure Active Directory Users' Enabled = $true Execute = { Get-MyUser } Processing = { } Summary = { } Variables = @{ } Solution = { if ($Script:Reporting['Users']['Data']) { New-HTMLTable -DataTable $Script:Reporting['Users']['Data'] -Filtering { New-HTMLTableCondition -Name 'Enabled' -Operator eq -Value $false -ComparisonType string -BackgroundColor Salmon New-HTMLTableCondition -Name 'Enabled' -Operator eq -Value $true -ComparisonType string -BackgroundColor SpringGreen New-HTMLTableCondition -Name 'IsSynchronized' -Operator eq -Value $false -ComparisonType string -BackgroundColor Salmon New-HTMLTableCondition -Name 'IsSynchronized' -Operator eq -Value $true -ComparisonType string -BackgroundColor SpringGreen New-HTMLTableCondition -Name 'LicensesStatus' -Operator contains -Value 'Direct' -ComparisonType string -BackgroundColor LightSkyBlue New-HTMLTableCondition -Name 'LicensesStatus' -Operator contains -Value 'Group' -ComparisonType string -BackgroundColor LightGreen New-HTMLTableCondition -Name 'LicensesStatus' -Operator contains -Value 'Duplicate' -ComparisonType string -BackgroundColor PeachOrange New-HTMLTableCondition -Name 'LicensesStatus' -Operator contains -Value 'Error' -ComparisonType string -BackgroundColor Salmon -HighlightHeaders 'LicensesStatus', 'LicensesErrors' New-HTMLTableCondition -Name 'LicensesStatus' -Operator eq -Value '' -ComparisonType string -BackgroundColor OldGold New-HTMLTableCondition -Name 'LastPasswordChangeDays' -Value 180 -Operator gt -ComparisonType number -BackgroundColor CoralRed -HighlightHeaders 'LastPasswordChangeDays', 'LastPasswordChangeDateTime' New-HTMLTableCondition -Name 'LastPasswordChangeDays' -Value 180 -Operator le -ComparisonType number -BackgroundColor SunsetOrange -HighlightHeaders 'LastPasswordChangeDays', 'LastPasswordChangeDateTime' New-HTMLTableCondition -Name 'LastPasswordChangeDays' -Value 90 -Operator le -ComparisonType number -BackgroundColor LaserLemon -HighlightHeaders 'LastPasswordChangeDays', 'LastPasswordChangeDateTime' New-HTMLTableCondition -Name 'LastPasswordChangeDays' -Value 30 -Operator le -ComparisonType number -BackgroundColor MediumSpringGreen -HighlightHeaders 'LastPasswordChangeDays', 'LastPasswordChangeDateTime' New-HTMLTableCondition -Name 'LastSynchronizedDays' -Value 180 -Operator gt -ComparisonType number -BackgroundColor CoralRed -HighlightHeaders 'LastSynchronizedDays', 'LastSynchronized' New-HTMLTableCondition -Name 'LastSynchronizedDays' -Value 180 -Operator le -ComparisonType number -BackgroundColor SunsetOrange -HighlightHeaders 'LastSynchronizedDays', 'LastSynchronized' New-HTMLTableCondition -Name 'LastSynchronizedDays' -Value 90 -Operator le -ComparisonType number -BackgroundColor LaserLemon -HighlightHeaders 'LastSynchronizedDays', 'LastSynchronized' New-HTMLTableCondition -Name 'LastSynchronizedDays' -Value 30 -Operator le -ComparisonType number -BackgroundColor MediumSpringGreen -HighlightHeaders 'LastSynchronizedDays', 'LastSynchronized' } -ScrollX } } } $Script:UsersPerLicense = [ordered] @{ Name = 'Azure Active Directory Users Per License' Enabled = $true Execute = { Get-MyUser -PerLicense } Processing = { } Summary = { } Variables = @{ } Solution = { if ($Script:Reporting['UsersPerLicense']['Data']) { New-HTMLTable -DataTable $Script:Reporting['UsersPerLicense']['Data'] -Filtering { New-HTMLTableCondition -Name 'AccountEnabled' -Operator eq -Value $false -ComparisonType string -BackgroundColor Salmon New-HTMLTableCondition -Name 'AccountEnabled' -Operator eq -Value $true -ComparisonType string -BackgroundColor SpringGreen foreach ($Name in $Script:Reporting['UsersPerLicense']['Data'][0].PSObject.Properties.Name) { if ($Name -notin 'DisplayName', 'Id', 'Enabled', 'UserPrincipalName', 'AccountEnabled', 'Mail' , 'Manager', 'LicensesStatus', 'LicensesErrors', 'Surname', 'LastPasswordChangeDateTime', 'GivenName', 'JobTitle') { New-HTMLTableCondition -Name $Name -Operator eq -Value 'Direct' -ComparisonType string -BackgroundColor GoldenFizz New-HTMLTableCondition -Name $Name -Operator eq -Value 'Group' -ComparisonType string -BackgroundColor LightGreen New-HTMLTableConditionGroup -Conditions { New-HTMLTableCondition -Name $Name -Operator ne -Value 'Group' -ComparisonType string New-HTMLTableCondition -Name $Name -Operator ne -Value 'Direct' -ComparisonType string New-HTMLTableCondition -Name $Name -Operator ne -Value '' -ComparisonType string } -Logic AND -BackgroundColor Orange -HighlightHeaders $Name } } } -ScrollX } } } $Script:UsersPerServicePlan = [ordered] @{ Name = 'Azure Active Directory Users Per Service Plan' Enabled = $true Execute = { Get-MyUser -PerServicePlan } Processing = { } Summary = { } Variables = @{ } Solution = { if ($Script:Reporting['UsersPerServicePlan']['Data']) { New-HTMLTable -DataTable $Script:Reporting['UsersPerServicePlan']['Data'] -Filtering { New-HTMLTableCondition -Name 'AccountEnabled' -Operator eq -Value $false -ComparisonType string -BackgroundColor Salmon New-HTMLTableCondition -Name 'AccountEnabled' -Operator eq -Value $true -ComparisonType string -BackgroundColor SpringGreen } -ScrollX } } } function Get-GitHubVersion { [cmdletBinding()] param( [Parameter(Mandatory)][string] $Cmdlet, [Parameter(Mandatory)][string] $RepositoryOwner, [Parameter(Mandatory)][string] $RepositoryName ) $App = Get-Command -Name $Cmdlet -ErrorAction SilentlyContinue if ($App) { [Array] $GitHubReleases = (Get-GitHubLatestRelease -Url "https://api.github.com/repos/$RepositoryOwner/$RepositoryName/releases" -Verbose:$false) $LatestVersion = $GitHubReleases[0] if (-not $LatestVersion.Errors) { if ($App.Version -eq $LatestVersion.Version) { "Current/Latest: $($LatestVersion.Version) at $($LatestVersion.PublishDate)" } elseif ($App.Version -lt $LatestVersion.Version) { "Current: $($App.Version), Published: $($LatestVersion.Version) at $($LatestVersion.PublishDate). Update?" } elseif ($App.Version -gt $LatestVersion.Version) { "Current: $($App.Version), Published: $($LatestVersion.Version) at $($LatestVersion.PublishDate). Lucky you!" } } else { "Current: $($App.Version)" } } } function New-HTMLReportGraphEssentials { [cmdletBinding()] param( [Array] $Type, [switch] $Online, [switch] $HideHTML, [string] $FilePath ) New-HTML -Author 'Przemysław Kłys @ Evotec' -TitleText 'GraphEssentials Report' { New-HTMLTabStyle -BorderRadius 0px -TextTransform capitalize -BackgroundColorActive SlateGrey New-HTMLSectionStyle -BorderRadius 0px -HeaderBackGroundColor Grey -RemoveShadow New-HTMLPanelStyle -BorderRadius 0px New-HTMLTableOption -DataStore JavaScript -BoolAsString -ArrayJoinString ', ' -ArrayJoin New-HTMLHeader { New-HTMLSection -Invisible { New-HTMLSection { New-HTMLText -Text "Report generated on $(Get-Date)" -Color Blue } -JustifyContent flex-start -Invisible New-HTMLSection { New-HTMLText -Text "GraphEssentials - $($Script:Reporting['Version'])" -Color Blue } -JustifyContent flex-end -Invisible } } if ($Type.Count -eq 1) { foreach ($T in $Script:GraphEssentialsConfiguration.Keys) { if ($Script:GraphEssentialsConfiguration[$T].Enabled -eq $true) { if ($Script:GraphEssentialsConfiguration[$T]['Summary']) { $Script:Reporting[$T]['Summary'] = Invoke-Command -ScriptBlock $Script:GraphEssentialsConfiguration[$T]['Summary'] } & $Script:GraphEssentialsConfiguration[$T]['Solution'] } } } else { foreach ($T in $Script:GraphEssentialsConfiguration.Keys) { if ($Script:GraphEssentialsConfiguration[$T].Enabled -eq $true) { if ($Script:GraphEssentialsConfiguration[$T]['Summary']) { $Script:Reporting[$T]['Summary'] = Invoke-Command -ScriptBlock $Script:GraphEssentialsConfiguration[$T]['Summary'] } New-HTMLTab -Name $Script:GraphEssentialsConfiguration[$T]['Name'] { & $Script:GraphEssentialsConfiguration[$T]['Solution'] } } } } } -Online:$Online.IsPresent -ShowHTML:(-not $HideHTML) -FilePath $FilePath } function New-HTMLReportGraphEssentialsWithSplit { [cmdletBinding()] param( [Array] $Type, [switch] $Online, [switch] $HideHTML, [string] $FilePath, [string] $CurrentReport ) # Split reports into multiple files for easier viewing $DateName = $(Get-Date -f yyyy-MM-dd_HHmmss) $FileName = [io.path]::GetFileNameWithoutExtension($FilePath) $DirectoryName = [io.path]::GetDirectoryName($FilePath) foreach ($T in $Script:GraphEssentialsConfiguration.Keys) { if ($Script:GraphEssentialsConfiguration[$T].Enabled -eq $true -and ((-not $CurrentReport) -or ($CurrentReport -and $CurrentReport -eq $T))) { $NewFileName = $FileName + '_' + $T + "_" + $DateName + '.html' $FilePath = [io.path]::Combine($DirectoryName, $NewFileName) New-HTML -Author 'Przemysław Kłys @ Evotec' -TitleText "GraphEssentials $CurrentReport Report" { New-HTMLTabStyle -BorderRadius 0px -TextTransform capitalize -BackgroundColorActive SlateGrey New-HTMLSectionStyle -BorderRadius 0px -HeaderBackGroundColor Grey -RemoveShadow New-HTMLPanelStyle -BorderRadius 0px New-HTMLTableOption -DataStore JavaScript -BoolAsString -ArrayJoinString ', ' -ArrayJoin New-HTMLHeader { New-HTMLSection -Invisible { New-HTMLSection { New-HTMLText -Text "Report generated on $(Get-Date)" -Color Blue } -JustifyContent flex-start -Invisible New-HTMLSection { New-HTMLText -Text "GraphEssentials - $($Script:Reporting['Version'])" -Color Blue } -JustifyContent flex-end -Invisible } } if ($Script:GraphEssentialsConfiguration[$T]['Summary']) { $Script:Reporting[$T]['Summary'] = Invoke-Command -ScriptBlock $Script:GraphEssentialsConfiguration[$T]['Summary'] } & $Script:GraphEssentialsConfiguration[$T]['Solution'] } -Online:$Online.IsPresent -ShowHTML:(-not $HideHTML) -FilePath $FilePath } } } function New-HTMLReportGraphUsage { [cmdletBinding()] param( [System.Collections.IDictionary] $Reports, [switch] $Online, [switch] $HideHTML, [string] $FilePath ) New-HTML -Author 'Przemysław Kłys @ Evotec' -TitleText 'GraphEssentials Usage Report' { New-HTMLTabStyle -BorderRadius 0px -TextTransform capitalize -BackgroundColorActive SlateGrey New-HTMLSectionStyle -BorderRadius 0px -HeaderBackGroundColor Grey -RemoveShadow New-HTMLPanelStyle -BorderRadius 0px New-HTMLTableOption -DataStore JavaScript -BoolAsString -ArrayJoinString ', ' -ArrayJoin New-HTMLHeader { New-HTMLSection -Invisible { New-HTMLSection { New-HTMLText -Text "Report generated on $(Get-Date)" -Color Blue } -JustifyContent flex-start -Invisible New-HTMLSection { New-HTMLText -Text "GraphEssentials - $($Script:Reporting['Version'])" -Color Blue } -JustifyContent flex-end -Invisible } } if ($Reports.Count -eq 1) { foreach ($T in $Reports.Keys) { New-HTMLTable -DataTable $Reports[$T] -Filtering { } -ScrollX } } else { foreach ($T in $Reports.Keys) { $Name = Format-AddSpaceToSentence -Text $T if ($Reports[$T].Count -gt 0) { $Name = "$Name 💚" } else { $Name = "$Name 💔" } New-HTMLTab -Name $Name { New-HTMLTable -DataTable $Reports[$T] -Filtering { } -ScrollX } } } } -Online:$Online.IsPresent -ShowHTML:(-not $HideHTML) -FilePath $FilePath } function Reset-GraphEssentials { [cmdletBinding()] param( ) if (-not $Script:DefaultTypes) { $Script:DefaultTypes = foreach ($T in $Script:GraphEssentialsConfiguration.Keys) { if ($Script:GraphEssentialsConfiguration[$T].Enabled) { $T } } } else { foreach ($T in $Script:GraphEssentialsConfiguration.Keys) { if ($Script:GraphEssentialsConfiguration[$T]) { $Script:GraphEssentialsConfiguration[$T]['Enabled'] = $false } } foreach ($T in $Script:DefaultTypes) { if ($Script:GraphEssentialsConfiguration[$T]) { $Script:GraphEssentialsConfiguration[$T]['Enabled'] = $true } } } } $Script:GraphEssentialsConfiguration = [ordered] @{ Apps = $Script:Apps AppsCredentials = $Script:AppsCredentials Devices = $Script:Devices DevicesIntune = $Script:DevicesIntune Licenses = $Script:Licenses Roles = $Script:Roles RolesUsers = $Script:RolesUsers RolesUsersPerColumn = $Script:RolesUsersPerColumn Users = $Script:Users UsersPerLicense = $Script:UsersPerLicense UsersPerServicePlan = $Script:UsersPerServicePlan Teams = $Script:Teams } function Get-MgToken { <# .SYNOPSIS Provides a way to get a token for Microsoft Graph API to be used with Connect-MGGraph .DESCRIPTION Provides a way to get a token for Microsoft Graph API to be used with Connect-MGGraph .PARAMETER ClientID Provide the Application ID of the App Registration .PARAMETER ClientSecret Provide the Client Secret of the App Registration .PARAMETER Credential Provide the Client Secret of the App Registration as a PSCredential .PARAMETER TenantID Provide the Tenant ID of the App Registration .PARAMETER Domain Provide the Domain of the tenant where the App is registred .EXAMPLE Get-MgToken -ClientID 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' -ClientSecret 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' -TenantID 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' .EXAMPLE Get-MgToken -ClientID 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' -ClientSecret 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' -Domain 'contoso.com' .EXAMPLE $ClientSecretEncrypted = 'ClientSecretToEncrypt' | ConvertTo-SecureString -AsPlainText | ConvertFrom-SecureString $AccessToken = Get-MgToken -Domain 'evotec.pl' -ClientID 'ClientID' -ClientSecretEncrypted $ClientSecretEncrypted Connect-MgGraph -AccessToken $AccessToken .NOTES General notes #> [CmdletBinding(DefaultParameterSetName = 'Domain')] param( [Parameter(ParameterSetName = 'TenantID', Mandatory)] [Parameter(ParameterSetName = 'Domain', Mandatory)] [Parameter(ParameterSetName = 'TenantIDEncrypted', Mandatory)] [Parameter(ParameterSetName = 'DomainEncrypted', Mandatory)] [alias('ApplicationID')][string] $ClientID, [Parameter(ParameterSetName = 'TenantID', Mandatory)] [Parameter(ParameterSetName = 'Domain', Mandatory)] [string] $ClientSecret, [Parameter(ParameterSetName = 'TenantIDEncrypted', Mandatory)] [Parameter(ParameterSetName = 'DomainEncrypted', Mandatory)] [string] $ClientSecretEncrypted, [Parameter(ParameterSetName = 'TenantIDEncrypted', Mandatory)] [Parameter(ParameterSetName = 'TenantID', Mandatory)][string] $TenantID, [Parameter(ParameterSetName = 'DomainEncrypted', Mandatory)] [Parameter(ParameterSetName = 'Domain', Mandatory)][string] $Domain, [Parameter(ParameterSetName = 'TenantID')] [Parameter(ParameterSetName = 'Domain')] [Parameter(ParameterSetName = 'TenantIDEncrypted')] [Parameter(ParameterSetName = 'DomainEncrypted')] [string] $Proxy, [Parameter(ParameterSetName = 'TenantID')] [Parameter(ParameterSetName = 'Domain')] [Parameter(ParameterSetName = 'TenantIDEncrypted')] [Parameter(ParameterSetName = 'DomainEncrypted')] [PSCredential] $ProxyCredential, [Parameter(ParameterSetName = 'TenantID')] [Parameter(ParameterSetName = 'Domain')] [Parameter(ParameterSetName = 'TenantIDEncrypted')] [Parameter(ParameterSetName = 'DomainEncrypted')] [switch] $ProxyUseDefaultCredentials ) if ($PSBoundParameters.ContainsKey('ClientSecretEncrypted')) { $TemporaryKey = ConvertTo-SecureString -String $ClientSecretEncrypted -Force $ApplicationKey = [System.Net.NetworkCredential]::new([string]::Empty, $TemporaryKey).Password } else { $ApplicationKey = $ClientSecret } $Body = @{ Grant_Type = "client_credentials" Scope = "https://graph.microsoft.com/.default" Client_Id = $ClientID Client_Secret = $ApplicationKey } if ($TenantID) { $Tenant = $TenantID } elseif ($Domain) { $Tenant = Get-O365TenantID -Domain $Domain } if (-not $Tenant) { throw "Get-MgToken - Unable to get Tenant ID" } $invokeRestMethodSplat = @{ Uri = "https://login.microsoftonline.com/$Tenant/oauth2/v2.0/token" Method = 'POST' Body = $Body } if ($PSBoundParameters.ContainsKey('Proxy')) { $invokeRestMethodSplat.Proxy = $Proxy } if ($PSBoundParameters.ContainsKey('ProxyCredential')) { $invokeRestMethodSplat.ProxyCredential = $ProxyCredential } if ($PSBoundParameters.ContainsKey('ProxyUseDefaultCredentials')) { $invokeRestMethodSplat.ProxyUseDefaultCredentials = $ProxyUseDefaultCredentials } $connection = Invoke-RestMethod @invokeRestMethodSplat $connection.access_token } function Get-MyApp { [cmdletBinding()] param( [string] $ApplicationName, [switch] $IncludeCredentials ) if ($ApplicationName) { $Application = Get-MgApplication -Filter "displayName eq '$ApplicationName'" -All -ConsistencyLevel eventual -Property Owners } else { $Application = Get-MgApplication -ConsistencyLevel eventual -All } $Applications = foreach ($App in $Application) { # Lets translate credentials to different format [Array] $AppCredentials = Get-MyAppCredentials -ApplicationList $App $Owners = Get-MgApplicationOwner -ApplicationId $App.Id -ConsistencyLevel eventual [Array] $DatesSorted = $AppCredentials.StartDateTime | Sort-Object # Lets find if description has email $DescriptionWithEmail = $false foreach ($CredentialName in $AppCredentials.KeyDisplayName) { if ($CredentialName -like '*@*') { $DescriptionWithEmail = $true break } } $DaysToExpireOldest = $AppCredentials.DaysToExpire | Sort-Object -Descending | Select-Object -Last 1 $DaysToExpireNewest = $AppCredentials.DaysToExpire | Sort-Object -Descending | Select-Object -First 1 if ($AppCredentials.Expired -contains $false) { $Expired = 'No' } elseif ($AppCredentials.Expired -contains $true) { $Expired = 'Yes' } else { $Expired = 'Not available' } $AppInformation = [ordered] @{ ObjectId = $App.Id ClientID = $App.AppId ApplicationName = $App.DisplayName OwnerDisplayName = $Owners.AdditionalProperties.displayName OwnerUserPrincipal = $Owners.AdditionalProperties.userPrincipalName OwnerMail = $Owners.AdditionalProperties.mail CreatedDate = $App.CreatedDateTime KeysCount = $AppCredentials.Count KeysTypes = $AppCredentials.Type KeysExpired = $Expired DaysToExpireOldest = $DaysToExpireOldest DaysToExpireNewest = $DaysToExpireNewest KeysDateOldest = if ($DatesSorted.Count -gt 0) { $DatesSorted[0] } else { } KeysDateNewest = if ($DatesSorted.Count -gt 0) { $DatesSorted[-1] } else { } KeysDescription = $AppCredentials.KeyDisplayName DescriptionWithEmail = $DescriptionWithEmail Notes = $App.Notes } if ($IncludeCredentials) { $AppInformation['Keys'] = $AppCredentials } [PSCustomObject] $AppInformation } $Applications } function Get-MyAppCredentials { [cmdletBinding()] param( [string] $ApplicationName, [int] $LessThanDaysToExpire, [int] $GreaterThanDaysToExpire, [switch] $Expired, [alias('DescriptionCredentials', 'ClientSecretName')][string] $DisplayNameCredentials, [Parameter(DontShow)][Array] $ApplicationList ) if (-not $ApplicationList) { if ($ApplicationName) { $ApplicationList = Get-MgApplication -Filter "displayName eq '$ApplicationName'" -All -ConsistencyLevel eventual } else { $ApplicationList = Get-MgApplication -All } } else { $ApplicationList = foreach ($App in $ApplicationList) { if ($PSBoundParameters.ContainsKey('ApplicationName')) { if ($App.DisplayName -eq $ApplicationName) { $App } } else { $App } } } $DateTimeNow = [DateTime]::Now $ApplicationsWithCredentials = foreach ($App in $ApplicationList) { if ($App.PasswordCredentials) { foreach ($Credentials in $App.PasswordCredentials) { if ($Credentials.EndDateTime -lt [DateTime]::Now) { $IsExpired = $true } else { $IsExpired = $false } if ($null -ne $Credentials.DisplayName) { $DisplayName = $Credentials.DisplayName } elseif ($null -ne $Credentials.CustomKeyIdentifier) { if ($Credentials.CustomKeyIdentifier[0] -eq 255 -and $Credentials.CustomKeyIdentifier[1] -eq 254 -and $Credentials.CustomKeyIdentifier[0] -ne 0 -and $Credentials.CustomKeyIdentifier[0] -ne 0) { $DisplayName = [System.Text.Encoding]::Unicode.GetString($Credentials.CustomKeyIdentifier) } elseif ($Credentials.CustomKeyIdentifier[0] -eq 255 -and $Credentials.CustomKeyIdentifier[1] -eq 254 -and $Credentials.CustomKeyIdentifier[0] -eq 0 -and $Credentials.CustomKeyIdentifier[0] -eq 0) { $DisplayName = [System.Text.Encoding]::UTF32.GetString($Credentials.CustomKeyIdentifier) } elseif ($Credentials.CustomKeyIdentifier[1] -eq 0 -and $Credentials.CustomKeyIdentifier[3] -eq 0) { $DisplayName = [System.Text.Encoding]::Unicode.GetString($Credentials.CustomKeyIdentifier) } else { $DisplayName = [System.Text.Encoding]::UTF8.GetString($Credentials.CustomKeyIdentifier) } } else { $DisplayName = $Null } $Creds = [PSCustomObject] @{ ObjectId = $App.Id ApplicationName = $App.DisplayName Type = 'Password' ClientID = $App.AppId CreatedDate = $App.CreatedDateTime KeyDisplayName = $DisplayName KeyId = $Credentials.KeyId #ClientSecret = $Credentials.SecretTex Hint = $Credentials.Hint Expired = $IsExpired DaysToExpire = ($Credentials.EndDateTime - $DateTimeNow).Days StartDateTime = $Credentials.StartDateTime EndDateTime = $Credentials.EndDateTime #CustomKeyIdentifier = $Credentials.CustomKeyIdentifier } if ($PSBoundParameters.ContainsKey('DisplayNameCredentials')) { if ($Creds.DisplayName -notlike $DisplayNameCredentials) { continue } } if ($PSBoundParameters.ContainsKey('LessThanDaysToExpire')) { if ($LessThanDaysToExpire -lt $Creds.DaysToExpire) { continue } } elseif ($PSBoundParameters.ContainsKey('Expired')) { if ($Creds.Expired -eq $false) { continue } } elseif ($PSBoundParameters.ContainsKey('GreaterThanDaysToExpire')) { if ($GreaterThanDaysToExpire -gt $Creds.DaysToExpire) { continue } } $Creds } } if ($App.KeyCredentials) { foreach ($Credentials in $App.KeyCredentials) { if ($Credentials.EndDateTime -lt [DateTime]::Now) { $IsExpired = $true } else { $IsExpired = $false } if ($null -ne $Credentials.DisplayName) { $DisplayName = $Credentials.DisplayName } elseif ($null -ne $Credentials.CustomKeyIdentifier) { if ($Credentials.CustomKeyIdentifier[0] -eq 255 -and $Credentials.CustomKeyIdentifier[1] -eq 254 -and $Credentials.CustomKeyIdentifier[0] -ne 0 -and $Credentials.CustomKeyIdentifier[0] -ne 0) { $DisplayName = [System.Text.Encoding]::Unicode.GetString($Credentials.CustomKeyIdentifier) } elseif ($Credentials.CustomKeyIdentifier[0] -eq 255 -and $Credentials.CustomKeyIdentifier[1] -eq 254 -and $Credentials.CustomKeyIdentifier[0] -eq 0 -and $Credentials.CustomKeyIdentifier[0] -eq 0) { $DisplayName = [System.Text.Encoding]::UTF32.GetString($Credentials.CustomKeyIdentifier) } elseif ($Credentials.CustomKeyIdentifier[1] -eq 0 -and $Credentials.CustomKeyIdentifier[3] -eq 0) { $DisplayName = [System.Text.Encoding]::Unicode.GetString($Credentials.CustomKeyIdentifier) } else { $DisplayName = [System.Text.Encoding]::UTF8.GetString($Credentials.CustomKeyIdentifier) } } else { $DisplayName = $Null } $Creds = [PSCustomObject] @{ ObjectId = $App.Id ApplicationName = $App.DisplayName Type = 'Certificate' ClientID = $App.AppId CreatedDate = $App.CreatedDateTime KeyDisplayName = $DisplayName KeyId = $Credentials.KeyId #ClientSecret = $Credentials.SecretTex Hint = $Credentials.Hint Expired = $IsExpired DaysToExpire = ($Credentials.EndDateTime - [DateTime]::Now).Days StartDateTime = $Credentials.StartDateTime EndDateTime = $Credentials.EndDateTime #CustomKeyIdentifier = $Credentials.CustomKeyIdentifier } if ($PSBoundParameters.ContainsKey('DisplayNameCredentials')) { if ($Creds.KeyDisplayName -notlike $DisplayNameCredentials) { continue } } if ($PSBoundParameters.ContainsKey('LessThanDaysToExpire')) { if ($LessThanDaysToExpire -lt $Creds.DaysToExpire) { continue } } elseif ($PSBoundParameters.ContainsKey('Expired')) { if ($Creds.Expired -eq $false) { continue } } elseif ($PSBoundParameters.ContainsKey('GreaterThanDaysToExpire')) { if ($GreaterThanDaysToExpire -gt $Creds.DaysToExpire) { continue } } $Creds } } } $ApplicationsWithCredentials } function Get-MyDefenderHealthIssues { <# .SYNOPSIS Retrieves health issues from Microsoft Graph Security API. .DESCRIPTION This function queries the Microsoft Graph Security API to retrieve health issues based on various filters such as status, health issue type, severity, and sensor DNS name. .PARAMETER Status The status of the health issues to retrieve. Valid values are 'open' and 'closed'. .PARAMETER HealthIssueType The type of health issues to retrieve. Valid values are 'global' and 'sensor'. .PARAMETER Severity The severity of the health issues to retrieve. Valid values are 'high', 'medium', and 'low'. .PARAMETER SensorDNSName The DNS name of the sensor for which to retrieve health issues. Health issues will be filtered to only include those that end with the specified sensor DNS name. .PARAMETER All A switch parameter. If specified, all health issues will be retrieved without applying any filters. .EXAMPLE Get-MyDefenderHealthIssues -Status 'open' -HealthIssueType 'global' -Severity 'high' Retrieves all open global health issues with high severity. .EXAMPLE Get-MyDefenderHealthIssues -SensorDNSName 'contoso.com' -All Retrieves all health issues for sensors whose DNS name ends with 'contoso.com', ignoring other filters. .NOTES Examples of Microsoft Graph Security API queries: - See all open health alerts: https://graph.microsoft.com/beta/security/identities/healthIssues?$filter=Status eq 'open' - See open Global health alerts: https://graph.microsoft.com/beta/security/identities/healthIssues?$filter=Status eq 'open' and healthIssueType eq 'global' - See open sensor health alerts: https://graph.microsoft.com/beta/security/identities/healthIssues?$filter=Status eq 'open' and healthIssueType eq 'sensor' - See open health alerts by severity: https://graph.microsoft.com/beta/security/identities/healthIssues?$filter=Status eq 'open' and severity eq 'medium' - See open global health alerts that domain name ends with contoso.com: https://graph.microsoft.com/beta/security/identities/healthissues?$filter=Status eq 'open' and healthIssueType eq 'global' and domainNames/any(s:endswith(s,'contoso.com')) - See open global health alerts that sensor DNS name ends with contoso.com: https://graph.microsoft.com/beta/security/identities/healthissues?$filter=Status eq 'open' and healthIssueType eq 'global' and sensorDNSNames/any(s:endswith(s,'contoso.com')) - See open sensor health alerts with sensor DNS name ends with contoso.corp: https://graph.microsoft.com/beta/security/identities/healthissues?$filter=Status eq 'open' and healthIssueType eq 'sensor' and sensorDNSNames/any(s:endswith(s,'contoso.corp')) #> [CmdletBinding()] param( [ValidateSet('open', 'closed')][string] $Status, [ValidateSet('global', 'sensor')][string] $HealthIssueType, [ValidateSet('high', 'medium', 'low')][string] $Severity, [string] $SensorDNSName, [switch] $All ) $QueryParameters = [ordered] @{ All = $All.IsPresent } if ($Status -and $HealthIssueType -and $Severity) { $QueryParameters.Add('$filter', "Status eq '$Status' and healthIssueType eq '$HealthIssueType' and severity eq '$Severity'") } elseif ($Status -and $HealthIssueType) { $QueryParameters.Add('$filter', "Status eq '$Status' and healthIssueType eq '$HealthIssueType'") } elseif ($Status -and $Severity) { $QueryParameters.Add('$filter', "Status eq '$Status' and severity eq '$Severity'") } elseif ($HealthIssueType -and $Severity) { $QueryParameters.Add('$filter', "healthIssueType eq '$HealthIssueType' and severity eq '$Severity'") } elseif ($Status) { $QueryParameters.Add('$filter', "Status eq '$Status'") } elseif ($HealthIssueType) { $QueryParameters.Add('$filter', "healthIssueType eq '$HealthIssueType'") } elseif ($Severity) { $QueryParameters.Add('$filter', "severity eq '$Severity'") } if ($SensorDNSName) { $newFilter = "sensorDNSNames/any(s:endswith(s,'$SensorDNSName'))" if ($QueryParameters.Contains('$filter')) { $QueryParameters['$filter'] += " and $newFilter" } else { $QueryParameters.Add('$filter', $newFilter) } } $Data = Get-MgBetaSecurityIdentityHealthIssue @QueryParameters $Data | ForEach-Object { [PSCustomObject] @{ DisplayName = $_.displayName # : Sensor service failed to start Status = $_.status # : open Severity = $_.severity # : high HealthIssueType = $_.healthIssueType # : sensor CreatedDateTime = $_.createdDateTime # : 2024 - 03 - 31 19:05:55 ModifiedDateTime = $_.lastModifiedDateTime # : 2024 - 05 - 03 10:55:20 SensorDNSNames = $_.sensorDNSNames # : { ADRODC.ad.evotec.pl } Description = $_.description # : The Sensor service on ADRODC.ad.evotec.pl failed to start. It was last seen running on 05 / 03 / 2024 10:24. Recommendations = $_.recommendations # : { Monitor Sensor logs to understand the root cause for Sensor service failure., Refer to the http: / / aka.ms / mdi / troubleshooting. } RecommendedActionCommands = $_.recommendedActionCommands # : {} Id = $_.id # : cafa6f51-be42 - 418a-968b-7cb529fb18ef DomainNames = $_.domainNames # : {} IssueTypeId = $_.issueTypeId # : AdditionalInformation = $_.additionalInformation # : {} } } } function Get-MyDevice { [cmdletBinding()] param( [ValidateSet('Hybrid AzureAD', 'AzureAD joined', 'AzureAD registered', 'Not available')][string[]] $Type, [switch] $Synchronized ) $TrustTypes = @{ 'ServerAD' = 'Hybrid AzureAD' 'AzureAD' = 'AzureAD joined' 'Workplace' = 'AzureAD registered' } $Today = Get-Date try { $Devices = Get-MgDevice -All -ExpandProperty RegisteredOwners -ErrorAction Stop } catch { Write-Warning -Message "Get-MyDevice - Failed to get devices. Error: $($_.Exception.Message)" return } foreach ($Device in $Devices) { if ($Device.ApproximateLastSignInDateTime) { $LastSeenDays = $( - $($Device.ApproximateLastSignInDateTime - $Today).Days) } else { $LastSeenDays = $null } if ($Device.OnPremisesLastSyncDateTime) { $LastSynchronizedDays = $( - $($Device.OnPremisesLastSyncDateTime - $Today).Days) } else { $LastSynchronizedDays = $null } if ($Device.TrustType) { $TrustType = $TrustTypes[$Device.TrustType] } else { $TrustType = 'Not available' } if ($Synchronized) { # Only return synchronized devices if (-not $Device.OnPremisesSyncEnabled) { continue } } if ($Type) { # Only return devices of the specified type if ($Type -notcontains $TrustType) { continue } } [PSCustomObject] @{ Name = $Device.DisplayName Id = $Device.Id Enabled = $Device.AccountEnabled OperatingSystem = $Device.OperatingSystem OperatingSystemVersion = $Device.OperatingSystemVersion TrustType = $TrustType ProfileType = $Device.ProfileType FirstSeen = $Device.AdditionalProperties.registrationDateTime LastSeen = $Device.ApproximateLastSignInDateTime LastSeenDays = $LastSeenDays Status = $Device.AdditionalProperties.deviceOwnership OwnerDisplayName = $Device.RegisteredOwners.AdditionalProperties.displayName OwnerEnabled = $Device.RegisteredOwners.AdditionalProperties.accountEnabled OwnerUserPrincipalName = $Device.RegisteredOwners.AdditionalProperties.userPrincipalName IsSynchronized = if ($Device.OnPremisesSyncEnabled) { $true } else { $false } LastSynchronized = $Device.OnPremisesLastSyncDateTime LastSynchronizedDays = $LastSynchronizedDays IsCompliant = $Device.IsCompliant IsManaged = $Device.IsManaged DeviceId = $Device.DeviceId Model = $Device.AdditionalProperties.model Manufacturer = $Device.AdditionalProperties.manufacturer ManagementType = $Device.AdditionalProperties.managementType EnrollmentType = $Device.AdditionalProperties.enrollmentType } } } function Get-MyDeviceIntune { [cmdletBinding()] param( ) $Today = Get-Date try { $DevicesIntune = Get-MgDeviceManagementManagedDevice -All -ErrorAction Stop } catch { Write-Warning -Message "Get-MyDeviceIntune - Failed to get intune devices. Error: $($_.Exception.Message)" return } foreach ($DeviceI in $DevicesIntune) { if ($DeviceI.LastSyncDateTime) { $LastSynchronizedDays = $( - $($DeviceI.LastSyncDateTime - $Today).Days) } else { $LastSynchronizedDays = $null } $DeviceInformation = [ordered] @{ Name = $DeviceI.DeviceName # : EVOMONSTER Id = $DeviceI.Id # : 83fe122f-c51c-49dc-a0f3-cc11d9e7d045 ComplianceState = $DeviceI.ComplianceState # : compliant OperatingSystem = $DeviceI.OperatingSystem # : Windows OperatingSystemVersion = $DeviceI.OSVersion # : 10.0.22621.1555 FirstSeen = $DeviceI.EnrolledDateTime # : 2023-01-28 10:34:18 LastSeen = $DeviceI.LastSyncDateTime # : 2023-04-14 04:52:42 LastSeenDays = $LastSynchronizedDays UserDisplayName = $DeviceI.UserDisplayName # : Przemysław Kłys UserId = $DeviceI.UserId # : e6a8f1cf-0874-4323-a12f-2bf51bb6dfdd UserPrincipalName = $DeviceI.UserPrincipalName # : przemyslaw.klys@evotec.pl EmailAddress = $DeviceI.EmailAddress # : przemyslaw.klys@evotec.pl ManagedDeviceName = $DeviceI.ManagedDeviceName # : przemyslaw.klys_Windows_1/28/2023_10:34 AM ManagedDeviceOwnerType = $DeviceI.ManagedDeviceOwnerType # : company ManagementAgent = $DeviceI.ManagementAgent # : mdm ManagementCertificateExpirationDate = $DeviceI.ManagementCertificateExpirationDate # : 2024-01-27 17:58:15 ActivationLockBypassCode = $DeviceI.ActivationLockBypassCode # : AndroidSecurityPatchLevel = $DeviceI.AndroidSecurityPatchLevel # : AzureAdDeviceId = $DeviceI.AzureAdDeviceId # : aee87706-674b-40be-8120-74e7c469329b AzureAdRegistered = $DeviceI.AzureAdRegistered # : True ComplianceGracePeriodExpirationDateTime = $DeviceI.ComplianceGracePeriodExpirationDateTime # : 9999-12-31 23:59:59 #ConfigurationManagerClientEnabledFeatures = $DeviceI.ConfigurationManagerClientEnabledFeatures # : Microsoft.Graph.PowerShell.Models.MicrosoftGraphConfigurationManagerClientEnabledFeatures DeviceActionResults = $DeviceI.DeviceActionResults # : {} #DeviceCategory = $DeviceI.DeviceCategory # : Microsoft.Graph.PowerShell.Models.MicrosoftGraphDeviceCategory DeviceCategoryName = $DeviceI.DeviceCategoryDisplayName # : Unknown DeviceCompliancePolicyStates = $DeviceI.DeviceCompliancePolicyStates # : DeviceConfigurationStates = $DeviceI.DeviceConfigurationStates # : DeviceEnrollmentType = $DeviceI.DeviceEnrollmentType # : windowsCoManagement #DeviceHealthAttestationState = $DeviceI.DeviceHealthAttestationState # : Microsoft.Graph.PowerShell.Models.MicrosoftGraphDeviceHealthAttestationState DeviceRegistrationState = $DeviceI.DeviceRegistrationState # : registered EasActivated = $DeviceI.EasActivated # : True EasActivationDateTime = $DeviceI.EasActivationDateTime # : 0001-01-01 00:00:00 EasDeviceId = $DeviceI.EasDeviceId # : E88398D87BD859566D129F86E2FD722C EthernetMacAddress = $DeviceI.EthernetMacAddress # : ExchangeAccessState = $DeviceI.ExchangeAccessState # : none ExchangeAccessStateReason = $DeviceI.ExchangeAccessStateReason # : none ExchangeLastSuccessfulSyncDateTime = $DeviceI.ExchangeLastSuccessfulSyncDateTime # : 0001-01-01 00:00:00 FreeStorageSpaceInBytes = $DeviceI.FreeStorageSpaceInBytes # : 1392111517696 Iccid = $DeviceI.Iccid # : Imei = $DeviceI.Imei # : IsEncrypted = $DeviceI.IsEncrypted # : True IsSupervised = $DeviceI.IsSupervised # : False IsJailBroken = $DeviceI.JailBroken # : Unknown Manufacturer = $DeviceI.Manufacturer # : ASUS Meid = $DeviceI.Meid # : Model = $DeviceI.Model # : System Product Name Notes = $DeviceI.Notes # : PartnerReportedThreatState = $DeviceI.PartnerReportedThreatState # : unknown PhoneNumber = $DeviceI.PhoneNumber # : PhysicalMemoryInBytes = $DeviceI.PhysicalMemoryInBytes # : 0 SerialNumber = $DeviceI.SerialNumber # : SystemSerialNumber SubscriberCarrier = $DeviceI.SubscriberCarrier # : TotalStorageSpaceInBytes = $DeviceI.TotalStorageSpaceInBytes # : 1999609266176 Udid = $DeviceI.Udid # : Users = $DeviceI.Users # : WiFiMacAddress = $DeviceI.WiFiMacAddress # : 8C1D96F0937B RemoteAssistanceSessionErrorDetails = $DeviceI.RemoteAssistanceSessionErrorDetails # : RemoteAssistanceSessionUrl = $DeviceI.RemoteAssistanceSessionUrl # : RequireUserEnrollmentApproval = $DeviceI.RequireUserEnrollmentApproval # : #AdditionalProperties = $DeviceI.AdditionalProperties # : {} } foreach ($D in $DeviceI.ConfigurationManagerClientEnabledFeatures.PSObject.Properties) { if ($D.Name -notin 'AdditionalProperties') { $DeviceInformation.Add("ConfigurationManagerClientEnabledFeatures$($D.Name)", $D.Value) } } foreach ($D in $DeviceI.DeviceCategory.PSObject.Properties) { if ($D.Name -notin 'AdditionalProperties') { $DeviceInformation.Add("DeviceCategory$($D.Name)", $D.Value) } } foreach ($D in $DeviceI.DeviceHealthAttestationState.PSObject.Properties) { if ($D.Name -notin 'AdditionalProperties') { $DeviceInformation.Add("DeviceHealthAttestationState$($D.Name)", $D.Value) } } [PSCustomObject] $DeviceInformation } } function Get-MyLicense { [CmdletBinding()] param( [Parameter(DontShow)][switch] $Internal ) $Skus = Get-MgSubscribedSku -All if ($Internal) { # This is used by Get-MyUser to get the list of licenses and service plans and faster search $Output = [ordered] @{ Licenses = [ordered] @{} ServicePlans = [ordered] @{} } foreach ($SKU in $Skus) { $Output['Licenses'][$Sku.SkuId] = Convert-Office365License -License $SKU.SkuPartNumber foreach ($Plan in $Sku.ServicePlans) { $Output['ServicePlans'][$Plan.ServicePlanId] = Convert-Office365License -License $Plan.ServicePlanName } } $Output } else { foreach ($SKU in $Skus) { if ($SKU.PrepaidUnits.Enabled -gt 0) { $LicensesUsedPercent = [math]::Round(($SKU.ConsumedUnits / $SKU.PrepaidUnits.Enabled) * 100, 0) } else { if ($SKU.ConsumedUnits -gt 0) { $LicensesUsedPercent = [math]::Round($SKU.ConsumedUnits * 100, 0) } else { $LicensesUsedPercent = 0 } } [PSCustomObject] @{ Name = Convert-Office365License -License $SKU.SkuPartNumber SkuId = $SKU.SkuId # : 26124093 - 3d78-432b-b5dc-48bf992543d5 SkuPartNumber = $SKU.SkuPartNumber # : IDENTITY_THREAT_PROTECTION AppliesTo = $SKU.AppliesTo # : User CapabilityStatus = $SKU.CapabilityStatus # : Enabled LicensesUsedPercent = $LicensesUsedPercent LicensesUsedCount = $SKU.ConsumedUnits # : 1 #Id = $SKU.Id # : ceb371f6 - 8745 - 4876-a040 - 69f2d10a9d1a_26124093-3d78-432b-b5dc-48bf992543d5 LicenseCountEnabled = $SKU.PrepaidUnits.Enabled LicenseCountWarning = $SKU.PrepaidUnits.Warning LicenseCountSuspended = $SKU.PrepaidUnits.Suspended #ServicePlans = $SKU.ServicePlans # : { MTP, SAFEDOCS, WINDEFATP, THREAT_INTELLIGENCE… } ServicePlansCount = $SKU.ServicePlans.Count # : 5 ServicePlans = $SKU.ServicePlans | ForEach-Object { Convert-Office365License -License $_.ServicePlanName } #AdditionalProperties = $SKU.AdditionalProperties # : {} } } } } function Get-MyRole { [CmdletBinding()] param( [switch] $OnlyWithMembers ) # $Users = Get-MgUser -All # #$Apps = Get-MgApplication -All # $Groups = Get-MgGroup -All -Filter "IsAssignableToRole eq true" # $ServicePrincipals = Get-MgServicePrincipal -All # #$DirectoryRole = Get-MgDirectoryRole -All # $Roles = Get-MgRoleManagementDirectoryRoleDefinition -All # $RolesAssignement = Get-MgRoleManagementDirectoryRoleAssignment -All #-ExpandProperty "principal" # $EligibilityAssignement = Get-MgRoleManagementDirectoryRoleEligibilitySchedule -All $ErrorsCount = 0 try { $Users = Get-MgUser -ErrorAction Stop -All -Property DisplayName, CreatedDateTime, 'AccountEnabled', 'Mail', 'UserPrincipalName', 'Id', 'UserType', 'OnPremisesDistinguishedName', 'OnPremisesSamAccountName', 'OnPremisesLastSyncDateTime', 'OnPremisesSyncEnabled', 'OnPremisesUserPrincipalName' } catch { Write-Warning -Message "Get-MyRoleUsers - Failed to get users. Error: $($_.Exception.Message)" $ErrorsCount++ } try { $Groups = Get-MgGroup -ErrorAction Stop -All -Filter "IsAssignableToRole eq true" -Property CreatedDateTime, Id, DisplayName, Mail, OnPremisesLastSyncDateTime, SecurityEnabled } catch { Write-Warning -Message "Get-MyRoleUsers - Failed to get groups. Error: $($_.Exception.Message)" $ErrorsCount++ } #$Apps = Get-MgApplication -All try { $ServicePrincipals = Get-MgServicePrincipal -ErrorAction Stop -All -Property CreatedDateTime, 'ServicePrincipalType', 'DisplayName', 'AccountEnabled', 'Id', 'AppID' } catch { Write-Warning -Message "Get-MyRoleUsers - Failed to get service principals. Error: $($_.Exception.Message)" $ErrorsCount++ } #$DirectoryRole = Get-MgDirectoryRole -All try { $Roles = Get-MgRoleManagementDirectoryRoleDefinition -ErrorAction Stop -All } catch { Write-Warning -Message "Get-MyRoleUsers - Failed to get roles. Error: $($_.Exception.Message)" $ErrorsCount++ } try { $RolesAssignement = Get-MgRoleManagementDirectoryRoleAssignment -ErrorAction Stop -All #-ExpandProperty "principal" } catch { Write-Warning -Message "Get-MyRoleUsers - Failed to get roles assignement. Error: $($_.Exception.Message)" $ErrorsCount++ } try { $EligibilityAssignement = Get-MgRoleManagementDirectoryRoleEligibilitySchedule -ErrorAction Stop -All } catch { Write-Warning -Message "Get-MyRoleUsers - Failed to get eligibility assignement. Error: $($_.Exception.Message)" $ErrorsCount++ } if ($ErrorsCount -gt 0) { return } $CacheUsersAndApps = [ordered] @{} foreach ($User in $Users) { $CacheUsersAndApps[$User.Id] = $User } foreach ($ServicePrincipal in $ServicePrincipals) { $CacheUsersAndApps[$ServicePrincipal.Id] = $ServicePrincipal } foreach ($Group in $Groups) { $CacheUsersAndApps[$Group.Id] = $Group } $CacheRoles = [ordered] @{} foreach ($Role in $Roles) { $CacheRoles[$Role.Id] = [ordered] @{ Role = $Role Direct = [System.Collections.Generic.List[object]]::new() Eligible = [System.Collections.Generic.List[object]]::new() Users = [System.Collections.Generic.List[object]]::new() ServicePrincipals = [System.Collections.Generic.List[object]]::new() Groups = [System.Collections.Generic.List[object]]::new() } } foreach ($Role in $RolesAssignement) { if ($CacheRoles[$Role.RoleDefinitionId]) { $CacheRoles[$Role.RoleDefinitionId].Direct.Add($CacheUsersAndApps[$Role.PrincipalId]) if ($CacheUsersAndApps[$Role.PrincipalId].GetType().Name -eq 'MicrosoftGraphUser') { $CacheRoles[$Role.RoleDefinitionId].Users.Add($CacheUsersAndApps[$Role.PrincipalId]) } elseif ($CacheUsersAndApps[$Role.PrincipalId].GetType().Name -eq 'MicrosoftGraphGroup') { $CacheRoles[$Role.RoleDefinitionId].Groups.Add($CacheUsersAndApps[$Role.PrincipalId]) } elseif ($CacheUsersAndApps[$Role.PrincipalId].GetType().Name -eq 'MicrosoftGraphServicePrincipal') { $CacheRoles[$Role.RoleDefinitionId].ServicePrincipals.Add($CacheUsersAndApps[$Role.PrincipalId]) } else { Write-Warning -Message "Unknown type for principal id $($Role.PrincipalId) - not supported yet!" } # MicrosoftGraphServicePrincipal, MicrosoftGraphUser,MicrosoftGraphGroup } else { try { $TemporaryRole = Get-MgRoleManagementDirectoryRoleDefinition -UnifiedRoleDefinitionId $Role.RoleDefinitionId -ErrorAction Stop } catch { Write-Warning -Message "Role $($Role.RoleDefinitionId) was not found. Using direct query failed." } if ($TemporaryRole) { Write-Verbose -Message "Role $($Role.RoleDefinitionId) was not found. Using direct query revealed $($TemporaryRole.DisplayName)." $CacheRoles[$Role.RoleDefinitionId] = [ordered] @{ Role = $TemporaryRole Direct = [System.Collections.Generic.List[object]]::new() Eligible = [System.Collections.Generic.List[object]]::new() Users = [System.Collections.Generic.List[object]]::new() ServicePrincipals = [System.Collections.Generic.List[object]]::new() Groups = [System.Collections.Generic.List[object]]::new() } $CacheRoles[$Role.RoleDefinitionId].Direct.Add($CacheUsersAndApps[$Role.PrincipalId]) if ($CacheUsersAndApps[$Role.PrincipalId].GetType().Name -eq 'MicrosoftGraphUser') { $CacheRoles[$Role.RoleDefinitionId].Users.Add($CacheUsersAndApps[$Role.PrincipalId]) } elseif ($CacheUsersAndApps[$Role.PrincipalId].GetType().Name -eq 'MicrosoftGraphGroup') { $CacheRoles[$Role.RoleDefinitionId].Groups.Add($CacheUsersAndApps[$Role.PrincipalId]) } elseif ($CacheUsersAndApps[$Role.PrincipalId].GetType().Name -eq 'MicrosoftGraphServicePrincipal') { $CacheRoles[$Role.RoleDefinitionId].ServicePrincipals.Add($CacheUsersAndApps[$Role.PrincipalId]) } else { Write-Warning -Message "Unknown type for principal id $($Role.PrincipalId) - not supported yet!" } } } } foreach ($Role in $EligibilityAssignement) { if ($CacheRoles[$Role.RoleDefinitionId]) { $CacheRoles[$Role.RoleDefinitionId].Eligible.Add($CacheUsersAndApps[$Role.PrincipalId]) if ($CacheUsersAndApps[$Role.PrincipalId].GetType().Name -eq 'MicrosoftGraphUser') { $CacheRoles[$Role.RoleDefinitionId].Users.Add($CacheUsersAndApps[$Role.PrincipalId]) } elseif ($CacheUsersAndApps[$Role.PrincipalId].GetType().Name -eq 'MicrosoftGraphGroup') { $CacheRoles[$Role.RoleDefinitionId].Groups.Add($CacheUsersAndApps[$Role.PrincipalId]) } elseif ($CacheUsersAndApps[$Role.PrincipalId].GetType().Name -eq 'MicrosoftGraphServicePrincipal') { $CacheRoles[$Role.RoleDefinitionId].ServicePrincipals.Add($CacheUsersAndApps[$Role.PrincipalId]) } else { Write-Warning -Message "Unknown type for principal id $($Role.PrincipalId) - not supported yet!" } } else { Write-Warning -Message $Role } } # lets get group members of groups we have members in and roles are there too $CacheGroupMembers = [ordered] @{} foreach ($Role in $CacheRoles.Keys) { if ($CacheRoles[$Role].Groups.Count -gt 0) { foreach ($Group in $CacheRoles[$Role].Groups) { if (-not $CacheGroupMembers[$Group.DisplayName]) { $CacheGroupMembers[$Group.DisplayName] = [System.Collections.Generic.List[object]]::new() $GroupMembers = Get-MgGroupMember -GroupId $Group.Id -All #-ErrorAction Stop foreach ($GroupMember in $GroupMembers) { $CacheGroupMembers[$Group.DisplayName].Add($CacheUsersAndApps[$GroupMember.Id]) } } } } } foreach ($Role in $CacheRoles.Keys) { if ($OnlyWithMembers) { if ($CacheRoles[$Role].Direct.Count -eq 0 -and $CacheRoles[$Role].Eligible.Count -eq 0) { continue } } $GroupMembersTotal = 0 foreach ($Group in $CacheRoles[$Role].Groups) { $GroupMembersTotal = + $CacheGroupMembers[$Group.DisplayName].Count } [PSCustomObject] @{ Name = $CacheRoles[$Role].Role.DisplayName Description = $CacheRoles[$Role].Role.Description IsBuiltin = $CacheRoles[$Role].Role.IsBuiltIn IsEnabled = $CacheRoles[$Role].Role.IsEnabled AllowedResourceActions = $CacheRoles[$Role].Role.RolePermissions[0].AllowedResourceActions.Count TotalMembers = $CacheRoles[$Role].Direct.Count + $CacheRoles[$Role].Eligible.Count + $GroupMembersTotal DirectMembers = $CacheRoles[$Role].Direct.Count EligibleMembers = $CacheRoles[$Role].Eligible.Count GroupsMembers = $GroupMembersTotal # here's a split by numbers Users = $CacheRoles[$Role].Users.Count ServicePrincipals = $CacheRoles[$Role].ServicePrincipals.Count Groups = $CacheRoles[$Role].Groups.Count } } } function Get-MyRoleUsers { [CmdletBinding()] param( [switch] $OnlyWithRoles, [switch] $RolePerColumn ) $ErrorsCount = 0 try { $Users = Get-MgUser -ErrorAction Stop -All -Property DisplayName, CreatedDateTime, 'AccountEnabled', 'Mail', 'UserPrincipalName', 'Id', 'UserType', 'OnPremisesDistinguishedName', 'OnPremisesSamAccountName', 'OnPremisesLastSyncDateTime', 'OnPremisesSyncEnabled', 'OnPremisesUserPrincipalName' } catch { Write-Warning -Message "Get-MyRoleUsers - Failed to get users. Error: $($_.Exception.Message)" $ErrorsCount++ } try { $Groups = Get-MgGroup -ErrorAction Stop -All -Filter "IsAssignableToRole eq true" -Property CreatedDateTime, Id, DisplayName, Mail, OnPremisesLastSyncDateTime, SecurityEnabled } catch { Write-Warning -Message "Get-MyRoleUsers - Failed to get groups. Error: $($_.Exception.Message)" $ErrorsCount++ } #$Apps = Get-MgApplication -All try { $ServicePrincipals = Get-MgServicePrincipal -ErrorAction Stop -All -Property CreatedDateTime, 'ServicePrincipalType', 'DisplayName', 'AccountEnabled', 'Id', 'AppID' } catch { Write-Warning -Message "Get-MyRoleUsers - Failed to get service principals. Error: $($_.Exception.Message)" $ErrorsCount++ } #$DirectoryRole = Get-MgDirectoryRole -All try { $Roles = Get-MgRoleManagementDirectoryRoleDefinition -ErrorAction Stop -All } catch { Write-Warning -Message "Get-MyRoleUsers - Failed to get roles. Error: $($_.Exception.Message)" $ErrorsCount++ } try { $RolesAssignement = Get-MgRoleManagementDirectoryRoleAssignment -ErrorAction Stop -All #-ExpandProperty "principal" } catch { Write-Warning -Message "Get-MyRoleUsers - Failed to get roles assignement. Error: $($_.Exception.Message)" $ErrorsCount++ } try { $EligibilityAssignement = Get-MgRoleManagementDirectoryRoleEligibilitySchedule -ErrorAction Stop -All } catch { Write-Warning -Message "Get-MyRoleUsers - Failed to get eligibility assignement. Error: $($_.Exception.Message)" $ErrorsCount++ } if ($ErrorsCount -gt 0) { return } $CacheUsersAndApps = [ordered] @{} foreach ($User in $Users) { $CacheUsersAndApps[$User.Id] = @{ Identity = $User Direct = [System.Collections.Generic.List[object]]::new() Eligible = [System.Collections.Generic.List[object]]::new() } } foreach ($ServicePrincipal in $ServicePrincipals) { $CacheUsersAndApps[$ServicePrincipal.Id] = @{ Identity = $ServicePrincipal Direct = [System.Collections.Generic.List[object]]::new() Eligible = [System.Collections.Generic.List[object]]::new() } } foreach ($Group in $Groups) { $CacheUsersAndApps[$Group.Id] = @{ Identity = $Group Direct = [System.Collections.Generic.List[object]]::new() Eligible = [System.Collections.Generic.List[object]]::new() } } $CacheRoles = [ordered] @{} foreach ($Role in $Roles) { $CacheRoles[$Role.Id] = [ordered] @{ Role = $Role Members = [System.Collections.Generic.List[object]]::new() Users = [System.Collections.Generic.List[object]]::new() ServicePrincipals = [System.Collections.Generic.List[object]]::new() GroupsDirect = [System.Collections.Generic.List[object]]::new() GroupsEligible = [System.Collections.Generic.List[object]]::new() } } foreach ($Role in $RolesAssignement) { if ($CacheRoles[$Role.RoleDefinitionId]) { $CacheUsersAndApps[$Role.PrincipalId].Direct.Add($CacheRoles[$Role.RoleDefinitionId].Role) if ($CacheUsersAndApps[$Role.PrincipalId].Identity.GetType().Name -eq 'MicrosoftGraphGroup') { $CacheRoles[$Role.RoleDefinitionId].GroupsDirect.Add($CacheUsersAndApps[$Role.PrincipalId].Identity) } } else { try { $TemporaryRole = Get-MgRoleManagementDirectoryRoleDefinition -UnifiedRoleDefinitionId $Role.RoleDefinitionId -ErrorAction Stop } catch { Write-Warning -Message "Role $($Role.RoleDefinitionId) was not found. Using direct query failed." } if ($TemporaryRole) { Write-Verbose -Message "Role $($Role.RoleDefinitionId) was not found. Using direct query revealed $($TemporaryRole.DisplayName)." if (-not $CacheRoles[$Role.RoleDefinitionId]) { $CacheRoles[$Role.RoleDefinitionId] = [ordered] @{ Role = $TemporaryRole Direct = [System.Collections.Generic.List[object]]::new() Eligible = [System.Collections.Generic.List[object]]::new() Users = [System.Collections.Generic.List[object]]::new() ServicePrincipals = [System.Collections.Generic.List[object]]::new() } } $CacheUsersAndApps[$Role.PrincipalId].Direct.Add($CacheRoles[$Role.RoleDefinitionId].Role) } } } foreach ($Role in $EligibilityAssignement) { if ($CacheRoles[$Role.RoleDefinitionId]) { $CacheUsersAndApps[$Role.PrincipalId].Eligible.Add($CacheRoles[$Role.RoleDefinitionId].Role) if ($CacheUsersAndApps[$Role.PrincipalId].Identity.GetType().Name -eq 'MicrosoftGraphGroup') { $CacheRoles[$Role.RoleDefinitionId].GroupsEligible.Add($CacheUsersAndApps[$Role.PrincipalId].Identity) } } else { Write-Warning -Message $Role } } $ListActiveRoles = foreach ($Identity in $CacheUsersAndApps.Keys) { if ($OnlyWithRoles) { if ($CacheUsersAndApps[$Identity].Direct.Count -eq 0 -and $CacheUsersAndApps[$Identity].Eligible.Count -eq 0) { continue } $CacheUsersAndApps[$Identity].Direct.DisplayName $CacheUsersAndApps[$Identity].Eligible.DisplayName } } # lets get group members of groups we have members in and roles are there too $CacheGroupMembers = [ordered] @{} $CacheUserMembers = [ordered] @{} foreach ($Role in $CacheRoles.Keys) { if ($CacheRoles[$Role].GroupsDirect.Count -gt 0) { foreach ($Group in $CacheRoles[$Role].GroupsDirect) { if (-not $CacheGroupMembers[$Group.DisplayName]) { $CacheGroupMembers[$Group.DisplayName] = [ordered] @{ Group = $Group Members = Get-MgGroupMember -GroupId $Group.Id -All } } foreach ($GroupMember in $CacheGroupMembers[$Group.DisplayName].Members) { #$CacheGroupMembers[$Group.DisplayName].Add($CacheUsersAndApps[$GroupMember.Id]) if (-not $CacheUserMembers[$GroupMember.Id]) { $CacheUserMembers[$GroupMember.Id] = [ordered] @{ Identity = $GroupMember Role = [ordered] @{} #Direct = [System.Collections.Generic.List[object]]::new() #Eligible = [System.Collections.Generic.List[object]]::new() } } #$CacheUserMembers[$GroupMember.Id].Direct.Add($Group) $RoleDisplayName = $CacheRoles[$Role].Role.DisplayName if (-not $CacheUserMembers[$GroupMember.Id]['Role'][$RoleDisplayName]) { $CacheUserMembers[$GroupMember.Id]['Role'][$RoleDisplayName] = [ordered] @{ Role = $CacheRoles[$Role].Role GroupsDirect = [System.Collections.Generic.List[object]]::new() GroupsEligible = [System.Collections.Generic.List[object]]::new() } } $CacheUserMembers[$GroupMember.Id]['Role'][$RoleDisplayName].GroupsDirect.Add($Group) } } } if ($CacheRoles[$Role].GroupsEligible.Count -gt 0) { foreach ($Group in $CacheRoles[$Role].GroupsEligible) { if (-not $CacheGroupMembers[$Group.DisplayName]) { $CacheGroupMembers[$Group.DisplayName] = [ordered] @{ Group = $Group Members = Get-MgGroupMember -GroupId $Group.Id -All } } foreach ($GroupMember in $CacheGroupMembers[$Group.DisplayName].Members) { if (-not $CacheUserMembers[$GroupMember.Id]) { $CacheUserMembers[$GroupMember.Id] = [ordered] @{ Identity = $GroupMember Role = [ordered] @{} #Direct = [System.Collections.Generic.List[object]]::new() #Eligible = [System.Collections.Generic.List[object]]::new() } } $RoleDisplayName = $CacheRoles[$Role].Role.DisplayName if (-not $CacheUserMembers[$GroupMember.Id]['Role'][$RoleDisplayName]) { $CacheUserMembers[$GroupMember.Id]['Role'][$RoleDisplayName] = [ordered] @{ Role = $CacheRoles[$Role].Role GroupsDirect = [System.Collections.Generic.List[object]]::new() GroupsEligible = [System.Collections.Generic.List[object]]::new() } } $CacheUserMembers[$GroupMember.Id]['Role'][$RoleDisplayName].GroupsEligible.Add($Group) #$CacheUserMembers[$GroupMember.Id].Eligible.Add($Group) } #} } } } foreach ($Identity in $CacheUsersAndApps.Keys) { $Type = if ($CacheUsersAndApps[$Identity].Identity.ServicePrincipalType) { $CacheUsersAndApps[$Identity].Identity.ServicePrincipalType } elseif ($CacheUsersAndApps[$Identity].Identity.UserType) { $CacheUsersAndApps[$Identity].Identity.UserType } elseif ($null -ne $CacheUsersAndApps[$Identity].Identity.SecurityEnabled) { if ($CacheUsersAndApps[$Identity].Identity.SecurityEnabled) { "SecurityGroup" } else { "DistributionGroup" } } else { "Unknown" } $IsSynced = if ($CacheUsersAndApps[$Identity].Identity.OnPremisesLastSyncDateTime) { 'Synchronized' } else { 'Online' } $CanonicalName = if ($CacheUsersAndApps[$Identity].Identity.OnPremisesDistinguishedName) { ConvertFrom-DistinguishedName -DistinguishedName $CacheUsersAndApps[$Identity].Identity.OnPremisesDistinguishedName -ToOrganizationalUnit } else { $null } if (-not $RolePerColumn) { if ($OnlyWithRoles) { if ($CacheUsersAndApps[$Identity].Direct.Count -eq 0 -and $CacheUsersAndApps[$Identity].Eligible.Count -eq 0) { continue } } [PSCustomObject] @{ Name = $CacheUsersAndApps[$Identity].Identity.DisplayName Enabled = $CacheUsersAndApps[$Identity].Identity.AccountEnabled Status = $IsSynced Type = $Type CreatedDateTime = $CacheUsersAndApps[$Identity].Identity.CreatedDateTime Mail = $CacheUsersAndApps[$Identity].Identity.Mail UserPrincipalName = $CacheUsersAndApps[$Identity].Identity.UserPrincipalName AppId = $CacheUsersAndApps[$Identity].Identity.AppID DirectCount = $CacheUsersAndApps[$Identity].Direct.Count EligibleCount = $CacheUsersAndApps[$Identity].Eligible.Count Direct = $CacheUsersAndApps[$Identity].Direct.DisplayName Eligible = $CacheUsersAndApps[$Identity].Eligible.DisplayName Location = $CanonicalName #OnPremisesSamAccountName = $CacheUsersAndApps[$Identity].Identity.OnPremisesSamAccountName #OnPremisesLastSyncDateTime = $CacheUsersAndApps[$Identity].Identity.OnPremisesLastSyncDateTime } } else { # we need to use different way to count roles for each user # this is because we also count the roles of users nested in groups $RolesCount = 0 $GroupNameMember = $CacheUserMembers[$CacheUsersAndApps[$Identity].Identity.Id] if ($GroupNameMember) { # $GroupNameMember['Role'] # $DirectRoles = $CacheUsersAndApps[$GroupNameMember.id].Direct # $EligibleRoles = $CacheUsersAndApps[$GroupNameMember.id].Eligible # $IdentityOfGroup = $CacheUsersAndApps[$GroupNameMember.id].Identity.DisplayName } else { # $DirectRoles = $null # $EligibleRoles = $null # $IdentityOfGroup = $null } $UserIdentity = [ordered] @{ Name = $CacheUsersAndApps[$Identity].Identity.DisplayName Enabled = $CacheUsersAndApps[$Identity].Identity.AccountEnabled Status = $IsSynced Type = $Type CreatedDateTime = $CacheUsersAndApps[$Identity].Identity.CreatedDateTime Mail = $CacheUsersAndApps[$Identity].Identity.Mail UserPrincipalName = $CacheUsersAndApps[$Identity].Identity.UserPrincipalName } foreach ($Role in $ListActiveRoles | Sort-Object -Unique) { $UserIdentity[$Role] = '' } foreach ($Role in $CacheUsersAndApps[$Identity].Eligible) { if (-not $UserIdentity[$Role.DisplayName] ) { $UserIdentity[$Role.DisplayName] = [System.Collections.Generic.List[string]]::new() } $UserIdentity[$Role.DisplayName].Add('Eligible') $RolesCount++ } foreach ($Role in $CacheUsersAndApps[$Identity].Direct) { if (-not $UserIdentity[$Role.DisplayName] ) { $UserIdentity[$Role.DisplayName] = [System.Collections.Generic.List[string]]::new() } $UserIdentity[$Role.DisplayName].Add('Direct') $RolesCount++ } if ($GroupNameMember) { foreach ($Role in $GroupNameMember['Role'].Keys) { foreach ($Group in $GroupNameMember['Role'][$Role].GroupsDirect) { if (-not $UserIdentity[$Role] ) { $UserIdentity[$Role] = [System.Collections.Generic.List[string]]::new() } $UserIdentity[$Role].Add($Group.DisplayName) $RolesCount++ } foreach ($Group in $GroupNameMember['Role'][$Role].GroupsEligible) { if (-not $UserIdentity[$Role] ) { $UserIdentity[$Role] = [System.Collections.Generic.List[string]]::new() } $UserIdentity[$Role].Add($Group.DisplayName) $RolesCount++ } } # foreach ($Role in $DirectRoles) { # if (-not $UserIdentity[$Role.DisplayName] ) { # $UserIdentity[$Role.DisplayName] = [System.Collections.Generic.List[string]]::new() # } # $UserIdentity[$Role.DisplayName].Add($IdentityOfGroup) # } # foreach ($Role in $EligibleRoles) { # if (-not $UserIdentity[$Role.DisplayName]) { # $UserIdentity[$Role.DisplayName] = [System.Collections.Generic.List[string]]::new() # } # $UserIdentity[$Role.DisplayName].Add($IdentityOfGroup) # } } $UserIdentity['Location'] = $CanonicalName if ($OnlyWithRoles) { if ($RolesCount -eq 0) { continue } } [PSCustomObject] $UserIdentity } } } function Get-MyTeam { [cmdletbinding()] param( [switch] $PerOwner, [switch] $AsHashtable ) $OwnerShip = [ordered] @{} # try { # $Url = "https://graph.microsoft.com/beta/teams" # $Teams1 = Do { # $TeamsRaw = Invoke-MgGraphRequest -Method GET -Uri $Url -ContentType 'application/json; charset=UTF-8' -ErrorAction Stop # if ($TeamsRaw.value) { # $TeamsRaw.value # } # if ($TeamsRaw."@odata.nextLink") { # $Url = $TeamsRaw."@odata.nextLink" # } # } While ($null -ne $TeamsRaw."@odata.nextLink") # } catch { # Write-Warning -Message "Get-MyTeam - Couldn't get list of teams. Error: $($_.Exception.Message)" # return # } try { $Teams = Get-MgTeam -All -ErrorAction Stop #-Property 'id','displayName','visibility','description','isArchived','summary' } catch { Write-Warning -Message "Get-MyTeam - Couldn't get list of teams. Error: $($_.Exception.Message)" return } foreach ($Team in $Teams) { try { $Owner = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/groups/$($Team.id)/owners" -ContentType 'application/json; charset=UTF-8' -ErrorAction Stop } catch { Write-Warning -Message "Get-MyTeam - Error list of owners on team $($Team.DisplayName) / $($Team.id): $($_.Exception.Message)" continue } try { $TeamDetails = Get-MgTeam -TeamId $Team.id -ErrorAction Stop } catch { Write-Warning -Message "Get-MyTeam - Error (extended) on team $($Team.DisplayName) / $($Team.id): $($_.Exception.Message)" continue } $TeamInformation = [ordered] @{ Id = $Team.id CreatedDateTime = $TeamDetails.createdDateTime Team = $Team.displayName Visibility = $Team.visibility OwnerCount = $Owner.value.Count MembersCount = $TeamDetails.Summary.MembersCount GuestsCount = $TeamDetails.Summary.GuestsCount Description = $Team.description OwnerDisplayName = $Owner.value.displayName OwnerMail = $Owner.value.mail OwnerUserPrincipalName = $Owner.value.userPrincipalName OwnerId = $Owner.value.id #IsArchived = $Team.isArchived GuestAllowCreateUpdateChannels = $TeamDetails.GuestSettings.AllowCreateUpdateChannels GuestAllowDeleteChannels = $TeamDetails.GuestSettings.AllowDeleteChannels AllowAddRemoveApps = $TeamDetails.MemberSettings.AllowAddRemoveApps AllowCreatePrivateChannels = $TeamDetails.MemberSettings.AllowCreatePrivateChannels AllowCreateUpdateChannels = $TeamDetails.MemberSettings.AllowCreateUpdateChannels AllowCreateUpdateRemoveConnectors = $TeamDetails.MemberSettings.AllowCreateUpdateRemoveConnectors AllowCreateUpdateRemoveTabs = $TeamDetails.MemberSettings.AllowCreateUpdateRemoveTabs AllowDeleteChannels = $TeamDetails.MemberSettings.AllowDeleteChannels #IsMembershipLimitedToOwners = $TeamDetails.MemberSettings.isMembershipLimitedToOwners } if ($PerOwner) { foreach ($O in $Owner.value) { if (-not $OwnerShip[$O.userPrincipalName]) { $OwnerShip[$O.userPrincipalName] = [System.Collections.Generic.List[PSCustomObject]]::new() } if ($AsHashtable) { $OwnerShip[$O.userPrincipalName].Add($TeamInformation) } else { $OwnerShip[$O.userPrincipalName].Add([PSCustomObject]$TeamInformation) } } } else { if ($AsHashtable) { $TeamInformation } else { [PSCustomObject]$TeamInformation } } } if ($PerOwner) { $OwnerShip } } function Get-MyTenantName { <# .SYNOPSIS Get Tenant Name from Tenant ID or Domain Name .DESCRIPTION Get Tenant Name from Tenant ID or Domain Name .PARAMETER TenantID Provide the Tenant ID of the Tenant .PARAMETER DomainName Provide the Domain Name of the Tenant .EXAMPLE Get-MyTenantName -TenantID 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' .EXAMPLE Get-MyTenantName -DomainName 'contoso.com' .NOTES General notes #> [CmdletBinding(DefaultParameterSetName = 'TenantID')] param( [Parameter(Mandatory, ParameterSetName = 'TenantID')][string] $TenantID, [Parameter(Mandatory, ParameterSetName = 'DomainName')][string] $DomainName ) if ($TenantID) { $Data = Invoke-MgRestMethod -Method GET -Uri "https://graph.microsoft.com/beta/tenantRelationships/findTenantInformationByTenantId(tenantId='$TenantID')" $Data } elseif ($DomainName) { $Data = Invoke-MgRestMethod -Method GET -Uri "https://graph.microsoft.com/beta/tenantRelationships/findTenantInformationByDomainName(domainName='$DomainName')" $Data } } function Get-MyUsageReports { [cmdletBinding(DefaultParameterSetName = "Period")] param( [parameter(ParameterSetName = 'Period', Mandatory)][ValidateSet('7', '30', '90', '180')][string] $Period, [parameter(ParameterSetName = 'DateTime', Mandatory)][DateTime] $DateTime, # last 30 days YYYY-MM-DD [parameter(Mandatory)][string][ValidateSet( 'EmailActivityCounts', 'EmailActivityUserCounts', 'EmailActivityUserDetail', 'EmailAppUsageAppsUserCounts', 'EmailAppUsageUserCounts', 'EmailAppUsageUserDetail', 'EmailAppUsageVersionsUserCounts', 'MailboxUsageDetail', 'MailboxUsageMailboxCounts', 'MailboxUsageQuotaStatusMailboxCounts', 'MailboxUsageStorage', 'Office365ActivationCounts', 'Office365ActivationsUserCounts', 'Office365ActivationsUserDetail', 'Office365ActiveUserCounts', 'Office365ActiveUserDetail', 'Office365GroupsActivityCounts', 'Office365GroupsActivityDetail', 'Office365GroupsActivityFileCounts', 'Office365GroupsActivityGroupCounts', 'Office365GroupsActivityStorage', 'Office365ServicesUserCounts', 'OneDriveActivityFileCounts', 'OneDriveActivityUserCounts', 'OneDriveActivityUserDetail', 'OneDriveUsageAccountCounts', 'OneDriveUsageAccountDetail', 'OneDriveUsageFileCounts', 'OneDriveUsageStorage', 'SharePointActivityFileCounts', 'SharePointActivityPages', 'SharePointActivityUserCounts', 'SharePointActivityUserDetail', 'SharePointSiteUsageDetail', 'SharePointSiteUsageFileCounts', 'SharePointSiteUsagePages', 'SharePointSiteUsageSiteCounts', 'SharePointSiteUsageStorage', 'SkypeForBusinessActivityCounts', 'SkypeForBusinessActivityUserCounts', 'SkypeForBusinessActivityUserDetail', 'SkypeForBusinessDeviceUsageDistributionUserCounts', 'SkypeForBusinessDeviceUsageUserCounts', 'SkypeForBusinessDeviceUsageUserDetail', 'SkypeForBusinessOrganizerActivityCounts', 'SkypeForBusinessOrganizerActivityMinuteCounts', 'SkypeForBusinessOrganizerActivityUserCounts', 'SkypeForBusinessParticipantActivityCounts', 'SkypeForBusinessParticipantActivityMinuteCounts', 'SkypeForBusinessParticipantActivityUserCounts', 'SkypeForBusinessPeerToPeerActivityCounts', 'SkypeForBusinessPeerToPeerActivityMinuteCounts', 'SkypeForBusinessPeerToPeerActivityUserCounts', 'TeamsDeviceUsageDistributionUserCounts', 'TeamsDeviceUsageUserCounts', 'TeamsDeviceUsageUserDetail', 'TeamsUserActivityCounts', 'TeamsUserActivityUserCounts', 'TeamsUserActivityUserDetail', 'YammerActivityCounts', 'YammerActivityUserCounts', 'YammerActivityUserDetail', 'YammerDeviceUsageDistributionUserCounts', 'YammerDeviceUsageUserCounts', 'YammerDeviceUsageUserDetail', 'YammerGroupsActivityCounts', 'YammerGroupsActivityDetail', 'YammerGroupsActivityGroupCounts' )] $Report ) if ($Period) { Write-Verbose -Message "Get-MyUsageReports - Report: $Report, Period: $Period" $DayPeriod = "D$Period" $Type = "(period='$DayPeriod')" } else { Write-Verbose -Message "Get-MyUsageReports - Report: $Report, DateTime: $DateTime" # last 30 days YYYY-MM-DD $DateTimeConverted = $DateTime.ToUniversalTime().ToString('yyyy-MM-dd') $Type = "(date=$DateTimeConverted)" } # main url $Url = "https://graph.microsoft.com/v1.0/reports/get$Report" # lets filter out the reports that do not support filtering, and apply some logic to let user get the data anyways if ($Report -in 'Office365ActivationCounts', 'Office365ActivationsUserCounts', 'Office365ActivationsUserDetail') { Write-Warning -Message "Get-MyUsageReports - $Report does not support filtering. Processing all data." } elseif ($Report -eq 'MailboxUsageDetail') { if ($Period) { $Url += "$Type" } else { Write-Warning -Message "Get-MyUsageReports - $Report does not support date filtering. Processing all data for period of 7 days." $Url += "(period='D7')" $Type = "(period='D7')" } } else { if ($Report -match 'Counts$|Pages$|Storage$') { if ($Period) { $Url += "$Type" } else { Write-Warning -Message "Get-MyUsageReports - $Report ending with Counts, Pages or Storage do not support date filtering. Processing data for last 7 days." $Url += "(period='D7')" } } else { $Url += "$Type" } } $TemporaryFile = [System.IO.Path]::GetTempFileName() try { Invoke-MgGraphRequest -Method GET -Uri $Url -ContentType "application/json" -OutputFilePath $TemporaryFile -ErrorAction Stop } catch { $ErrorDefault = $_.Exception.Message $ErrorDetails = $_.ErrorDetails.Message # get only the last line of the error message if ($ErrorDetails) { $ErrorDetails = $ErrorDetails.Split("`n")[-1] Try { $ErrorJSON = $ErrorDetails | ConvertFrom-Json -ErrorAction Stop } catch { Write-Warning -Message "Get-MyUsageReports - Error when requesting data for $Report $Type. Error: $ErrorDefault" } try { $NestedError = $ErrorJSON.error.message | ConvertFrom-Json -ErrorAction Stop $FinalErrorMessage = $NestedError.error.message Write-Warning -Message "Get-MyUsageReports - Error when requesting data for $Report $Type. Error: $FinalErrorMessage" } catch { Write-Warning -Message "Get-MyUsageReports - Error when requesting data for $Report $Type. Error: $ErrorDefault" } } else { Write-Warning -Message "Get-MyUsageReports - Error when requesting data for $Report $Type. Error: $ErrorDefault" } } if (Test-Path -LiteralPath $TemporaryFile) { try { $CSV = Import-Csv -LiteralPath $TemporaryFile -ErrorAction Stop -Encoding Unicode $CSV } catch { Write-Warning -Message "Get-MyUsageReports - Error when importing data $Report $Type. Error: $($_.Exception.Message)" } try { Remove-Item -LiteralPath $TemporaryFile -ErrorAction Stop } catch { Write-Warning -Message "Get-MyUsageReports - Error when removing temporary file $Report $Type. Error: $($_.Exception.Message)" } } } function Get-MyUser { [CmdletBinding(DefaultParameterSetName = 'Default')] param( [Parameter(ParameterSetName = 'PerLicense')][switch] $PerLicense, [Parameter(ParameterSetName = 'PerServicePlan')][switch] $PerServicePlan ) $Today = Get-Date $Properties = @( 'LicenseAssignmentStates', 'AccountEnabled', 'AssignedLicenses', 'AssignedPlans', 'DisplayName', 'Id', 'GivenName', 'SurName', 'JobTitle', 'LastPasswordChangeDateTime', 'Mail', 'Manager' 'OnPremisesLastSyncDateTime', 'OnPremisesSyncEnabled', 'OnPremisesDistinguishedName', 'UserPrincipalName' ) Write-Verbose -Message "Get-MyUser - Getting list of licenses" $AllLicenses = Get-MyLicense -Internal $AllLicensesValues = $AllLicenses['Licenses'].Values | Sort-Object $AllServicePlansValues = $AllLicenses['ServicePlans'].Values | Sort-Object $getMgUserSplat = @{ All = $true Property = $Properties } Write-Verbose -Message "Get-MyUser - Getting list of all users" $StartTime = [System.Diagnostics.Stopwatch]::StartNew() $AllUsers = Get-MgUser @getMgUserSplat -ExpandProperty Manager $EndTime = Stop-TimeLog -Time $StartTime -Option OneLiner Write-Verbose -Message "Get-MyUser - Got $($AllUsers.Count) users in $($EndTime). Now processing them." $StartTime = [System.Diagnostics.Stopwatch]::StartNew() $Count = 0 foreach ($User in $AllUsers) { $Count++ Write-Verbose -Message "Get-MyUser - Processing $($User.DisplayName) - $Count/$($AllUsers.Count)" if ($User.LastPasswordChangeDateTime) { $LastPasswordChangeDays = $( - $($User.LastPasswordChangeDateTime - $Today).Days) } else { $LastPasswordChangeDays = $null } if ($User.OnPremisesLastSyncDateTime) { $LastSynchronizedDays = $( - $($User.OnPremisesLastSyncDateTime - $Today).Days) } else { $LastSynchronizedDays = $null } $OutputUser = [ordered] @{ 'DisplayName' = $User.DisplayName 'Id' = $User.Id 'UserPrincipalName' = $User.UserPrincipalName 'GivenName' = $User.GivenName 'SurName' = $User.SurName 'Enabled' = $User.AccountEnabled 'JobTitle' = $User.JobTitle 'Mail' = $User.Mail 'Manager' = if ($User.Manager.Id) { $User.Manager.Id } else { $null } 'ManagerDisplayName' = if ($User.Manager.Id) { $User.Manager.AdditionalProperties.displayName } else { $null } 'ManagerUserPrincipalName' = if ($User.Manager.Id) { $User.Manager.AdditionalProperties.userPrincipalName } else { $null } 'ManagerIsSynchronized' = if ($User.Manager.Id) { if ($User.Manager.AdditionalProperties.onPremisesSyncEnabled) { $User.Manager.AdditionalProperties.onPremisesSyncEnabled } else { $false } } else { $null } 'LastPasswordChangeDateTime' = $User.LastPasswordChangeDateTime 'LastPasswordChangeDays' = $LastPasswordChangeDays 'IsSynchronized' = if ($User.OnPremisesSyncEnabled) { $User.OnPremisesSyncEnabled } else { $null } 'LastSynchronized' = $User.OnPremisesLastSyncDateTime 'LastSynchronizedDays' = $LastSynchronizedDays 'OnPremisesDistinguishedName' = $User.OnPremisesDistinguishedName } if ($PerLicense) { $LicensesErrors = [System.Collections.Generic.List[string]]::new() $OutputUser['NotMatched'] = [System.Collections.Generic.List[string]]::new() foreach ($License in $AllLicensesValues) { $OutputUser[$License] = [System.Collections.Generic.List[string]]::new() } foreach ($License in $User.LicenseAssignmentStates) { try { $LicenseFound = $AllLicenses['Licenses'][$License.SkuId] if ($LicenseFound) { if ($License.State -eq 'Active' -and $License.AssignedByGroup.Count -gt 0) { $OutputUser[$LicenseFound].Add('Group') } elseif ($License.State -eq 'Active' -and $License.AssignedByGroup.Count -eq 0) { $OutputUser[$LicenseFound].Add('Direct') } } else { if ($License.State -eq 'Active' -and $License.AssignedByGroup.Count -gt 0) { $OutputUser['DifferentLicense'].Add("Group $($License.SkuId)") } elseif ($License.State -eq 'Active' -and $License.AssignedByGroup.Count -eq 0) { $OutputUser['DifferentLicense'].Add("Direct $($License.SkuId)") } Write-Warning -Message "$($License.SkuId) not found in AllLicenses" $LicensesErrors.Add("License ID $($License.SkuId) not found in All Licenses") } } catch { Write-Warning -Message "Error processing $($License.SkuId) for $($User.DisplayName)" } } $OutputUser['LicensesErrors'] = $LicensesErrors | Sort-Object -Unique } elseif ($PerServicePlan) { $OutputUser['DeletedServicePlans'] = [System.Collections.Generic.List[string]]::new() foreach ($ServicePlan in $AllServicePlansValues) { $OutputUser[$ServicePlan] = '' } foreach ($ServicePlan in $User.AssignedPlans) { if ($AllLicenses['ServicePlans'][$ServicePlan.ServicePlanId]) { $OutputUser[$AllLicenses['ServicePlans'][$ServicePlan.ServicePlanId]] = 'Assigned' } else { if ($ServicePlan.CapabilityStatus -ne 'Deleted') { Write-Warning -Message "$($ServicePlan.ServicePlanId) $($ServicePlan.Service) not found in AllLicenses" } else { $OutputUser['DeletedServicePlans'].Add($ServicePlan.ServicePlanId) } } } } else { $LicensesList = [System.Collections.Generic.List[string]]::new() $LicensesStatus = [System.Collections.Generic.List[string]]::new() $LicensesErrors = [System.Collections.Generic.List[string]]::new() $User.LicenseAssignmentStates | ForEach-Object { if ($LicensesList -notcontains $AllLicenses['Licenses'][$_.SkuId]) { $LicensesList.Add($AllLicenses['Licenses'][$_.SkuId]) if ($_.State -eq 'Active' -and $_.AssignedByGroup.Count -gt 0) { $LicensesStatus.Add('Group') } elseif ($_.State -eq 'Active' -and $_.AssignedByGroup.Count -eq 0) { $LicensesStatus.Add('Direct') } else { $LicensesStatus.Add($_.State) if ($LicensesErrors -notcontains $_.Error) { $LicensesErrors.Add($_.Error) } } } else { $LicensesStatus.Add("Duplicate") } } $Plans = foreach ($Object in $User.AssignedPlans) { if ($Object.CapabilityStatus -ne 'Deleted') { $AllLicenses['ServicePlans'][$Object.ServicePlanId] } } $OutputUser['LicensesStatus'] = $LicensesStatus | Sort-Object -Unique $OutputUser['LicensesErrors'] = $LicensesErrors $OutputUser['Licenses'] = $LicensesList $OutputUser['Plans'] = $Plans } [PSCustomObject] $OutputUser } $EndTime = Stop-TimeLog -Time $StartTime -Option OneLiner Write-Verbose -Message "Get-MyUser - Processed all users in $($EndTime)." } function Invoke-MyGraphEssentials { [cmdletBinding()] param( [string] $FilePath, [Parameter(Position = 0)][string[]] $Type, [switch] $PassThru, [switch] $HideHTML, [switch] $HideSteps, [switch] $ShowError, [switch] $ShowWarning, [switch] $Online, [switch] $SplitReports ) Reset-GraphEssentials #$Script:AllUsers = [ordered] @{} $Script:Cache = [ordered] @{} $Script:Reporting = [ordered] @{} $Script:Reporting['Version'] = Get-GitHubVersion -Cmdlet 'Invoke-MyGraphEssentials' -RepositoryOwner 'evotecit' -RepositoryName 'GraphEssentials' $Script:Reporting['Settings'] = @{ ShowError = $ShowError.IsPresent ShowWarning = $ShowWarning.IsPresent HideSteps = $HideSteps.IsPresent } Write-Color '[i]', "[GraphEssentials] ", 'Version', ' [Informative] ', $Script:Reporting['Version'] -Color Yellow, DarkGray, Yellow, DarkGray, Magenta # Verify requested types are supported $Supported = [System.Collections.Generic.List[string]]::new() [Array] $NotSupported = foreach ($T in $Type) { if ($T -notin $Script:GraphEssentialsConfiguration.Keys ) { $T } else { $Supported.Add($T) } } if ($Supported) { Write-Color '[i]', "[GraphEssentials] ", 'Supported types', ' [Informative] ', "Chosen by user: ", ($Supported -join ', ') -Color Yellow, DarkGray, Yellow, DarkGray, Yellow, Magenta } if ($NotSupported) { Write-Color '[i]', "[GraphEssentials] ", 'Not supported types', ' [Informative] ', "Following types are not supported: ", ($NotSupported -join ', ') -Color Yellow, DarkGray, Yellow, DarkGray, Yellow, Magenta Write-Color '[i]', "[GraphEssentials] ", 'Not supported types', ' [Informative] ', "Please use one/multiple from the list: ", ($Script:GraphEssentialsConfiguration.Keys -join ', ') -Color Yellow, DarkGray, Yellow, DarkGray, Yellow, Magenta return } if ($FilePath) { $Directory = Split-Path -Path $FilePath -Parent if (-not (Test-Path -Path $Directory)) { Write-Color '[i]', "[GraphEssentials] ", 'Creating directory', ' [Informative] ', $Directory -Color Yellow, DarkGray, Yellow, DarkGray New-Item -Path $Directory -ItemType Directory -Force } if ($FilePath -notlike '*.html') { Write-Color '[i]', "[GraphEssentials] ", 'Invalid file path', ' [Error] ', "File path must end with .html" -Color Yellow, DarkGray, Yellow, DarkGray, Red return } } # Lets make sure we only enable those types which are requestd by user if ($Type) { foreach ($T in $Script:GraphEssentialsConfiguration.Keys) { $Script:GraphEssentialsConfiguration[$T].Enabled = $false } # Lets enable all requested ones foreach ($T in $Type) { $Script:GraphEssentialsConfiguration[$T].Enabled = $true } } # Build data foreach ($T in $Script:GraphEssentialsConfiguration.Keys) { if ($Script:GraphEssentialsConfiguration[$T].Enabled -eq $true) { $Script:Reporting[$T] = [ordered] @{ Name = $Script:GraphEssentialsConfiguration[$T].Name ActionRequired = $null Data = $null Exclusions = $null WarningsAndErrors = $null Time = $null Summary = $null Variables = Copy-Dictionary -Dictionary $Script:GraphEssentialsConfiguration[$T]['Variables'] } if ($Exclusions) { if ($Exclusions -is [scriptblock]) { $Script:Reporting[$T]['ExclusionsCode'] = $Exclusions } if ($Exclusions -is [Array]) { $Script:Reporting[$T]['Exclusions'] = $Exclusions } } $TimeLogGraphEssentials = Start-TimeLog Write-Color -Text '[i]', '[Start] ', $($Script:GraphEssentialsConfiguration[$T]['Name']) -Color Yellow, DarkGray, Yellow $OutputCommand = Invoke-Command -ScriptBlock $Script:GraphEssentialsConfiguration[$T]['Execute'] -WarningVariable CommandWarnings -ErrorVariable CommandErrors #-ArgumentList $Forest, $ExcludeDomains, $IncludeDomains if ($OutputCommand -is [System.Collections.IDictionary]) { # in some cases the return will be wrapped in Hashtable/orderedDictionary and we need to handle this without an array $Script:Reporting[$T]['Data'] = $OutputCommand } else { # since sometimes it can be 0 or 1 objects being returned we force it being an array $Script:Reporting[$T]['Data'] = [Array] $OutputCommand } Invoke-Command -ScriptBlock $Script:GraphEssentialsConfiguration[$T]['Processing'] $Script:Reporting[$T]['WarningsAndErrors'] = @( if ($ShowWarning) { foreach ($War in $CommandWarnings) { [PSCustomObject] @{ Type = 'Warning' Comment = $War Reason = '' TargetName = '' } } } if ($ShowError) { foreach ($Err in $CommandErrors) { [PSCustomObject] @{ Type = 'Error' Comment = $Err Reason = $Err.CategoryInfo.Reason TargetName = $Err.CategoryInfo.TargetName } } } ) $TimeEndGraphEssentials = Stop-TimeLog -Time $TimeLogGraphEssentials -Option OneLiner $Script:Reporting[$T]['Time'] = $TimeEndGraphEssentials Write-Color -Text '[i]', '[End ] ', $($Script:GraphEssentialsConfiguration[$T]['Name']), " [Time to execute: $TimeEndGraphEssentials]" -Color Yellow, DarkGray, Yellow, DarkGray if ($SplitReports) { Write-Color -Text '[i]', '[HTML ] ', 'Generating HTML report for ', $T -Color Yellow, DarkGray, Yellow $TimeLogHTML = Start-TimeLog New-HTMLReportGraphEssentialsWithSplit -FilePath $FilePath -Online:$Online -HideHTML:$HideHTML -CurrentReport $T $TimeLogEndHTML = Stop-TimeLog -Time $TimeLogHTML -Option OneLiner Write-Color -Text '[i]', '[HTML ] ', 'Generating HTML report for ', $T, " [Time to execute: $TimeLogEndHTML]" -Color Yellow, DarkGray, Yellow, DarkGray } } } if (-not $SplitReports) { Write-Color -Text '[i]', '[HTML ] ', 'Generating HTML report' -Color Yellow, DarkGray, Yellow $TimeLogHTML = Start-TimeLog if (-not $FilePath) { $FilePath = Get-FileName -Extension 'html' -Temporary } New-HTMLReportGraphEssentials -Type $Type -Online:$Online.IsPresent -HideHTML:$HideHTML.IsPresent -FilePath $FilePath $TimeLogEndHTML = Stop-TimeLog -Time $TimeLogHTML -Option OneLiner Write-Color -Text '[i]', '[HTML ] ', 'Generating HTML report', " [Time to execute: $TimeLogEndHTML]" -Color Yellow, DarkGray, Yellow, DarkGray } Reset-GraphEssentials if ($PassThru) { $Script:Reporting } } [scriptblock] $SourcesAutoCompleter = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $Script:GraphEssentialsConfiguration.Keys | Sort-Object | Where-Object { $_ -like "*$wordToComplete*" } } Register-ArgumentCompleter -CommandName Invoke-MyGraphEssentials -ParameterName Type -ScriptBlock $SourcesAutoCompleter function Invoke-MyGraphUsageReports { [CmdletBinding()] param( [parameter(ParameterSetName = 'Period', Mandatory)][ValidateSet('7', '30', '90', '180')][string] $Period, [parameter(ParameterSetName = 'DateTime', Mandatory)][DateTime] $DateTime, # last 30 days YYYY-MM-DD [parameter(Mandatory)][string[]][ValidateSet( 'All', 'EmailActivityCounts', 'EmailActivityUserCounts', 'EmailActivityUserDetail', 'EmailAppUsageAppsUserCounts', 'EmailAppUsageUserCounts', 'EmailAppUsageUserDetail', 'EmailAppUsageVersionsUserCounts', 'MailboxUsageDetail', 'MailboxUsageMailboxCounts', 'MailboxUsageQuotaStatusMailboxCounts', 'MailboxUsageStorage', 'Office365ActivationCounts', 'Office365ActivationsUserCounts', 'Office365ActivationsUserDetail', 'Office365ActiveUserCounts', 'Office365ActiveUserDetail', 'Office365GroupsActivityCounts', 'Office365GroupsActivityDetail', 'Office365GroupsActivityFileCounts', 'Office365GroupsActivityGroupCounts', 'Office365GroupsActivityStorage', 'Office365ServicesUserCounts', 'OneDriveActivityFileCounts', 'OneDriveActivityUserCounts', 'OneDriveActivityUserDetail', 'OneDriveUsageAccountCounts', 'OneDriveUsageAccountDetail', 'OneDriveUsageFileCounts', 'OneDriveUsageStorage', 'SharePointActivityFileCounts', 'SharePointActivityPages', 'SharePointActivityUserCounts', 'SharePointActivityUserDetail', 'SharePointSiteUsageDetail', 'SharePointSiteUsageFileCounts', 'SharePointSiteUsagePages', 'SharePointSiteUsageSiteCounts', 'SharePointSiteUsageStorage', 'SkypeForBusinessActivityCounts', 'SkypeForBusinessActivityUserCounts', 'SkypeForBusinessActivityUserDetail', 'SkypeForBusinessDeviceUsageDistributionUserCounts', 'SkypeForBusinessDeviceUsageUserCounts', 'SkypeForBusinessDeviceUsageUserDetail', 'SkypeForBusinessOrganizerActivityCounts', 'SkypeForBusinessOrganizerActivityMinuteCounts', 'SkypeForBusinessOrganizerActivityUserCounts', 'SkypeForBusinessParticipantActivityCounts', 'SkypeForBusinessParticipantActivityMinuteCounts', 'SkypeForBusinessParticipantActivityUserCounts', 'SkypeForBusinessPeerToPeerActivityCounts', 'SkypeForBusinessPeerToPeerActivityMinuteCounts', 'SkypeForBusinessPeerToPeerActivityUserCounts', 'TeamsDeviceUsageDistributionUserCounts', 'TeamsDeviceUsageUserCounts', 'TeamsDeviceUsageUserDetail', 'TeamsUserActivityCounts', 'TeamsUserActivityUserCounts', 'TeamsUserActivityUserDetail', 'YammerActivityCounts', 'YammerActivityUserCounts', 'YammerActivityUserDetail', 'YammerDeviceUsageDistributionUserCounts', 'YammerDeviceUsageUserCounts', 'YammerDeviceUsageUserDetail', 'YammerGroupsActivityCounts', 'YammerGroupsActivityDetail', 'YammerGroupsActivityGroupCounts' )] $Report, [switch] $Online, [switch] $HideHTML, [string] $FilePath, [switch] $DontSuppress ) $Script:Reporting = [ordered] @{} $Script:Reporting['Version'] = Get-GitHubVersion -Cmdlet 'Invoke-MyGraphEssentials' -RepositoryOwner 'evotecit' -RepositoryName 'GraphEssentials' $Script:Reporting['Reports'] = [ordered] @{} if ($Report -contains 'All') { $ParameterList = (Get-Command -Name Get-MyUsageReports).Parameters $Report = $ParameterList["Report"].Attributes.ValidValues } foreach ($R in $Report) { $Splat = @{ Report = $R Period = $Period DateTime = $DateTime } Remove-EmptyValue -Hashtable $Splat $Script:Reporting['Reports'][$R] = Get-MyUsageReports @Splat } $newHTMLReportGraphUsageSplat = @{ Reports = $Script:Reporting['Reports'] Online = $Online HideHTML = $HideHTML FilePath = $FilePath } New-HTMLReportGraphUsage @newHTMLReportGraphUsageSplat if ($DontSuppress) { $Script:Reporting } } function New-MyApp { [cmdletBinding()] param( [parameter(Mandatory)][alias('AppName', 'DisplayName')][string] $ApplicationName, [parameter(Mandatory)][alias('DescriptionCredentials')][string] $DisplayNameCredentials, [string] $Description, [int] $MonthsValid = 12, [switch] $RemoveOldCredentials, [switch] $ServicePrincipal ) $Application = Get-MgApplication -Filter "displayName eq '$ApplicationName'" -All -ErrorAction Stop if (-not $Application) { Write-Verbose -Message "New-MyApp - Creating application $ApplicationName" $newMgApplicationSplat = @{ DisplayName = $ApplicationName Description = $Description } Remove-EmptyValue -Hashtable $newMgApplicationSplat $Application = New-MgApplication @newMgApplicationSplat -ErrorAction Stop } else { Write-Verbose -Message "New-MyApp - Application $ApplicationName already exists. Reusing..." } if ($RemoveOldCredentials -and $Application.PasswordCredentials.Count -gt 0) { foreach ($Credential in $Application.PasswordCredentials) { Write-Verbose -Message "New-MyApp - Removing old credential $($Credential.KeyId) / $($Credential.DisplayName)" try { Remove-MgApplicationPassword -ApplicationId $Application.Id -KeyId $Credential.KeyId -ErrorAction Stop } catch { Write-Warning -Message "New-MyApp - Failed to remove old credential $($Credential.KeyId) / $($Credential.DisplayName)" return } } } $Credentials = New-MyAppCredentials -ObjectID $Application.Id -DisplayName $DisplayNameCredentials -MonthsValid $MonthsValid if ($Application -and $Credentials) { [PSCustomObject] @{ ObjectID = $Application.Id ApplicationName = $Application.DisplayName ClientID = $Application.AppId ClientSecretName = $Credentials.DisplayName ClientSecret = $Credentials.SecretText ClientSecretID = $Credentials.KeyID DaysToExpire = ($Credentials.EndDateTime - [DateTime]::Now).Days StartDateTime = $Credentials.StartDateTime EndDateTime = $Credentials.EndDateTime } } else { Write-Warning -Message "New-MyApp - Application or credentials for $ApplicationName was not created." } if ($ServicePrincipal) { $ServicePrincipalApp = Get-MgServicePrincipal -Filter "appId eq '$($Application.AppId)'" -All -ConsistencyLevel eventual -ErrorAction Stop if (-not $ServicePrincipalApp) { Write-Verbose -Message "New-MyApp - Creating service principal for $ApplicationName" try { $null = New-MgServicePrincipal -AppId $Application.AppId -AccountEnabled:$true -ErrorAction Stop } catch { Write-Warning -Message "New-MyApp - Failed to create service principal for $ApplicationName. Error: $($_.Exception.Message)" } } else { Write-Verbose -Message "New-MyApp - Service principal for $ApplicationName already exists. Skipping..." } } } function New-MyAppCredentials { [cmdletbinding(DefaultParameterSetName = 'AppName')] param( [parameter(Mandatory, ParameterSetName = 'AppId')][string] $ObjectID, [alias('AppName')] [parameter(Mandatory, ParameterSetName = 'AppName')][string] $ApplicationName, [string] $DisplayName, [int] $MonthsValid = 12 ) if ($AppName) { $Application = Get-MgApplication -Filter "DisplayName eq '$ApplicationName'" -ConsistencyLevel eventual -All if ($Application) { $ID = $Application.Id } else { Write-Warning -Message "Application with name '$ApplicationName' not found" return } } else { $ID = $ObjectID } $PasswordCredential = [Microsoft.Graph.PowerShell.Models.IMicrosoftGraphPasswordCredential] @{ StartDateTime = [datetime]::Now } if ($DisplayName) { $PasswordCredential.DisplayName = $DisplayName } $PasswordCredential.EndDateTime = [datetime]::Now.AddMonths($MonthsValid) try { Add-MgApplicationPassword -ApplicationId $ID -PasswordCredential $PasswordCredential -ErrorAction Stop } catch { Write-Warning -Message "Failed to add password credential to application $ID / $ApplicationName. Error: $($_.Exception.Message)" } } function Remove-MyAppCredentials { [cmdletBinding(SupportsShouldProcess)] param( [string] $ApplicationName, [int] $LessThanDaysToExpire, [int] $GreaterThanDaysToExpire, [switch] $Expired, [alias('DescriptionCredentials')][string] $DisplayNameCredentials ) $getMyAppCredentialsSplat = @{} if ($PSBoundParameters.ContainsKey('ApplicationName')) { $getMyAppCredentialsSplat.ApplicationName = $ApplicationName } if ($PSBoundParameters.ContainsKey('LessThanDaysToExpire')) { $getMyAppCredentialsSplat.LessThanDaysToExpire = $LessThanDaysToExpire } if ($PSBoundParameters.ContainsKey('Expired')) { $getMyAppCredentialsSplat.Expired = $Expired } if ($PSBoundParameters.ContainsKey('DisplayNameCredentials')) { $getMyAppCredentialsSplat.DisplayNameCredentials = $DisplayNameCredentials } if ($PSBoundParameters.ContainsKey('GreaterThanDaysToExpire')) { $getMyAppCredentialsSplat.GreaterThanDaysToExpire = $GreaterThanDaysToExpire } $Applications = Get-MyAppCredentials @getMyAppCredentialsSplat foreach ($App in $Applications) { Write-Verbose -Message "Processing application $($App.ApplicationName) for key removal $($App.KeyDisplayName)/$($App.KeyId) - Start: $($App.StartDateTime), End: $($App.EndDateTime), IsExpired: $($App.Expired)" if ($PSCmdlet.ShouldProcess($App.ApplicationName, "Remove $($App.KeyDisplayName)/$($App.KeyId)")) { try { # it has it's own whatif, but it looks ugly Remove-MgApplicationPassword -ApplicationId $App.ObjectID -KeyId $App.KeyId -ErrorAction Stop } catch { Write-Warning -Message "Failed to remove $($App.KeyDisplayName)/$($App.KeyId) from $($App.ApplicationName). Error: $($_.Exception.Message)" } } } } function Send-MyApp { [cmdletBinding()] param( [parameter(Mandatory)][Array] $ApplicationName, [parameter(Mandatory)][string] $EmailFrom, [parameter(Mandatory)][string[]] $EmailTo, [string] $EmailSubject = 'Service Principal for Applications', [parameter(Mandatory)][string] $Domain, [switch] $RemoveOldCredentials ) $TenantID = Get-O365TenantID -Domain $Domain $Applications = foreach ($App in $ApplicationName) { if ($App -is [string]) { $DisplayNameCredentials = $EmailTo -join ";" New-MyApp -ApplicationName $App -DisplayNameCredentials $DisplayNameCredentials -Verbose -RemoveOldCredentials:$RemoveOldCredentials.IsPresent } else { if ($App.DisplayNameCredentials) { New-MyApp @App } else { $DisplayNameCredentials = $EmailTo -join ";" New-MyApp @App -DisplayNameCredentials $DisplayNameCredentials -Verbose -ServicePrincipal -RemoveOldCredentials:$RemoveOldCredentials.IsPresent } } } $EmailBody = EmailBody { EmailText -Text "Hello," -LineBreak EmailText -Text @( "As per your request we have created following Service Principal for you:" ) EmailText -LineBreak foreach ($Application in $Applications) { EmailText -Text @( "Application ", $Application.ApplicationName, " credentials are: " ) -Color None, BlueDiamond, None -TextDecoration none, underline, none -FontWeight normal, bold, normal EmailList { EmailListItem -Text "Application Name: ", $Application.ApplicationName -Color None, BlueDiamond, None -FontWeight normal, bold, normal EmailListItem -Text "Client ID: ", $Application.ClientID -Color None, BlueDiamond, None -FontWeight normal, bold, normal EmailListItem -Text "Client SecretID: ", $Application.ClientSecretID -Color None, BlueDiamond, None -FontWeight normal, bold, normal EmailListItem -Text "Client Secret: ", $Application.ClientSecret -Color None, BlueDiamond, None -FontWeight normal, bold, normal EmailListItem -Text "Expires: ", $Application.EndDateTime, " (Valid days: $($Application.DaysToExpire))" -Color None, BlueDiamond, None -FontWeight normal, bold, normal } } EmailText -LineBreak EmailText -Text @( "If required TenantID/DirectoryID is: ", $TenantID ) -LineBreak -Color None, LawnGreen -FontWeight normal, bold EmailText -Text @( "Please remove this email from your inbox once you have copied the credentials into secure place." ) -FontWeight normal, normal, bold, normal, normal -Color None, None, Salmon, None, None -LineBreak EmailText -Text "Thank you" } $EmailStatus = Send-EmailMessage -From $EmailFrom -To $EmailTo -HTML $EmailBody -Subject $EmailSubject -Verbose -Priority Normal -MgGraphRequest [ordered] @{ EmailStatus = $EmailStatus Applications = $Applications } } function Show-MyApp { [cmdletBinding()] param( [Parameter(Mandatory)][string] $FilePath, [switch] $Online, [switch] $ShowHTML ) $Script:Reporting = [ordered] @{} $Script:Reporting['Version'] = Get-GitHubVersion -Cmdlet 'Invoke-MyGraphEssentials' -RepositoryOwner 'evotecit' -RepositoryName 'GraphEssentials' $Applications = Get-MyApp $ApplicationsPassword = Get-MyAppCredentials New-HTML { New-HTMLTabStyle -BorderRadius 0px -TextTransform capitalize -BackgroundColorActive SlateGrey New-HTMLSectionStyle -BorderRadius 0px -HeaderBackGroundColor Grey -RemoveShadow New-HTMLPanelStyle -BorderRadius 0px New-HTMLTableOption -DataStore JavaScript -BoolAsString -ArrayJoinString ', ' -ArrayJoin New-HTMLHeader { New-HTMLSection -Invisible { New-HTMLSection { New-HTMLText -Text "Report generated on $(Get-Date)" -Color Blue } -JustifyContent flex-start -Invisible New-HTMLSection { New-HTMLText -Text "GraphEssentials - $($Script:Reporting['Version'])" -Color Blue } -JustifyContent flex-end -Invisible } } New-HTMLSection -HeaderText "Applications" { New-HTMLTable -DataTable $Applications -Filtering { New-TableEvent -ID 'TableAppsCredentials' -SourceColumnID 0 -TargetColumnID 0 } -DataStore JavaScript -DataTableID "TableApps" -PagingLength 5 -ScrollX } New-HTMLSection -HeaderText 'Applications Credentials' { New-HTMLTable -DataTable $ApplicationsPassword -Filtering { New-HTMLTableCondition -Name 'DaysToExpire' -Value 30 -Operator 'ge' -BackgroundColor Conifer -ComparisonType number New-HTMLTableCondition -Name 'DaysToExpire' -Value 30 -Operator 'lt' -BackgroundColor Orange -ComparisonType number New-HTMLTableCondition -Name 'DaysToExpire' -Value 5 -Operator 'lt' -BackgroundColor Red -ComparisonType number New-HTMLTableCondition -Name 'Expired' -Value $true -ComparisonType string -BackgroundColor Salmon -FailBackgroundColor Conifer } -DataStore JavaScript -DataTableID "TableAppsCredentials" -ScrollX } } -ShowHTML:$ShowHTML.IsPresent -FilePath $FilePath -Online:$Online.IsPresent } # Export functions and aliases as required Export-ModuleMember -Function @('Get-MgToken', 'Get-MyApp', 'Get-MyAppCredentials', 'Get-MyDefenderHealthIssues', 'Get-MyDevice', 'Get-MyDeviceIntune', 'Get-MyLicense', 'Get-MyRole', 'Get-MyRoleUsers', 'Get-MyTeam', 'Get-MyTenantName', 'Get-MyUsageReports', 'Get-MyUser', 'Invoke-MyGraphEssentials', 'Invoke-MyGraphUsageReports', 'New-MyApp', 'New-MyAppCredentials', 'Remove-MyAppCredentials', 'Send-MyApp', 'Show-MyApp') -Alias @() # SIG # Begin signature block # MIItqwYJKoZIhvcNAQcCoIItnDCCLZgCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCByLjcGI4Pnl/79 # lmegqgCGIECmIfzGuaCfQQlA11EWaqCCJq4wggWNMIIEdaADAgECAhAOmxiO+dAt # 5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV # BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBa # Fw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy # dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD # ZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC # ggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3E # MB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKy # unWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsF # xl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU1 # 5zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJB # MtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObUR # WBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6 # nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxB # YKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5S # UUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+x # q4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIB # NjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwP # TzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMC # AYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp # Y2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv # bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0 # aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENB # LmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0Nc # Vec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnov # Lbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65Zy # oUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFW # juyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPF # mCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9z # twGpn1eqXijiuZQwggWQMIIDeKADAgECAhAFmxtXno4hMuI5B72nd3VcMA0GCSqG # SIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx # GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRy # dXN0ZWQgUm9vdCBHNDAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGIx # CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 # dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBH # NDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL/mkHNo3rvkXUo8MCIw # aTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/zG6Q4FutWxpdtHauyefLK # EdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZanMylNEQRBAu34LzB4Tm # dDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7sWxq868nPzaw0QF+xembu # d8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL2pNe3I6PgNq2kZhAkHnD # eMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfbBHMqbpEBfCFM1LyuGwN1 # XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3JFxGj2T3wWmIdph2PVld # QnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3cAORFJYm2mkQZK37AlLTS # YW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqxYxhElRp2Yn72gLD76GSm # M9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0viastkF13nqsX40/ybzT # QRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aLT8LWRV+dIPyhHsXAj6Kx # fgommfXkaS+YHS312amyHeUbAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD # VR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwPTzANBgkq # hkiG9w0BAQwFAAOCAgEAu2HZfalsvhfEkRvDoaIAjeNkaA9Wz3eucPn9mkqZucl4 # XAwMX+TmFClWCzZJXURj4K2clhhmGyMNPXnpbWvWVPjSPMFDQK4dUPVS/JA7u5iZ # aWvHwaeoaKQn3J35J64whbn2Z006Po9ZOSJTROvIXQPK7VB6fWIhCoDIc2bRoAVg # X+iltKevqPdtNZx8WorWojiZ83iL9E3SIAveBO6Mm0eBcg3AFDLvMFkuruBx8lbk # apdvklBtlo1oepqyNhR6BvIkuQkRUNcIsbiJeoQjYUIp5aPNoiBB19GcZNnqJqGL # FNdMGbJQQXE9P01wI4YMStyB0swylIQNCAmXHE/A7msgdDDS4Dk0EIUhFQEI6FUy # 3nFJ2SgXUE3mvk3RdazQyvtBuEOlqtPDBURPLDab4vriRbgjU2wGb2dVf0a1TD9u # KFp5JtKkqGKX0h7i7UqLvBv9R0oN32dmfrJbQdA75PQ79ARj6e/CVABRoIoqyc54 # zNXqhwQYs86vSYiv85KZtrPmYQ/ShQDnUBrkG5WdGaG5nLGbsQAe79APT0JsyQq8 # 7kP6OnGlyE0mpTX9iV28hWIdMtKgK1TtmlfB2/oQzxm3i0objwG2J5VT6LaJbVu8 # aNQj6ItRolb58KaAoNYes7wPD1N1KarqE3fk3oyBIa0HEEcRrYc9B9F1vM/zZn4w # ggauMIIElqADAgECAhAHNje3JFR82Ees/ShmKl5bMA0GCSqGSIb3DQEBCwUAMGIx # CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 # dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBH # NDAeFw0yMjAzMjMwMDAwMDBaFw0zNzAzMjIyMzU5NTlaMGMxCzAJBgNVBAYTAlVT # MRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1 # c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwggIiMA0GCSqG # SIb3DQEBAQUAA4ICDwAwggIKAoICAQDGhjUGSbPBPXJJUVXHJQPE8pE3qZdRodbS # g9GeTKJtoLDMg/la9hGhRBVCX6SI82j6ffOciQt/nR+eDzMfUBMLJnOWbfhXqAJ9 # /UO0hNoR8XOxs+4rgISKIhjf69o9xBd/qxkrPkLcZ47qUT3w1lbU5ygt69OxtXXn # HwZljZQp09nsad/ZkIdGAHvbREGJ3HxqV3rwN3mfXazL6IRktFLydkf3YYMZ3V+0 # VAshaG43IbtArF+y3kp9zvU5EmfvDqVjbOSmxR3NNg1c1eYbqMFkdECnwHLFuk4f # sbVYTXn+149zk6wsOeKlSNbwsDETqVcplicu9Yemj052FVUmcJgmf6AaRyBD40Nj # gHt1biclkJg6OBGz9vae5jtb7IHeIhTZgirHkr+g3uM+onP65x9abJTyUpURK1h0 # QCirc0PO30qhHGs4xSnzyqqWc0Jon7ZGs506o9UD4L/wojzKQtwYSH8UNM/STKvv # mz3+DrhkKvp1KCRB7UK/BZxmSVJQ9FHzNklNiyDSLFc1eSuo80VgvCONWPfcYd6T # /jnA+bIwpUzX6ZhKWD7TA4j+s4/TXkt2ElGTyYwMO1uKIqjBJgj5FBASA31fI7tk # 42PgpuE+9sJ0sj8eCXbsq11GdeJgo1gJASgADoRU7s7pXcheMBK9Rp6103a50g5r # mQzSM7TNsQIDAQABo4IBXTCCAVkwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4E # FgQUuhbZbU2FL3MpdpovdYxqII+eyG8wHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5n # P+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMIMHcG # CCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQu # Y29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGln # aUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8v # Y3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAgBgNV # HSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEwDQYJKoZIhvcNAQELBQADggIB # AH1ZjsCTtm+YqUQiAX5m1tghQuGwGC4QTRPPMFPOvxj7x1Bd4ksp+3CKDaopafxp # wc8dB+k+YMjYC+VcW9dth/qEICU0MWfNthKWb8RQTGIdDAiCqBa9qVbPFXONASIl # zpVpP0d3+3J0FNf/q0+KLHqrhc1DX+1gtqpPkWaeLJ7giqzl/Yy8ZCaHbJK9nXzQ # cAp876i8dU+6WvepELJd6f8oVInw1YpxdmXazPByoyP6wCeCRK6ZJxurJB4mwbfe # Kuv2nrF5mYGjVoarCkXJ38SNoOeY+/umnXKvxMfBwWpx2cYTgAnEtp/Nh4cku0+j # Sbl3ZpHxcpzpSwJSpzd+k1OsOx0ISQ+UzTl63f8lY5knLD0/a6fxZsNBzU+2QJsh # IUDQtxMkzdwdeDrknq3lNHGS1yZr5Dhzq6YBT70/O3itTK37xJV77QpfMzmHQXh6 # OOmc4d0j/R0o08f56PGYX/sr2H7yRp11LB4nLCbbbxV7HhmLNriT1ObyF5lZynDw # N7+YAN8gFk8n+2BnFqFmut1VwDophrCYoCvtlUG3OtUVmDG0YgkPCr2B2RP+v6TR # 81fZvAT6gt4y3wSJ8ADNXcL50CN/AAvkdgIm2fBldkKmKYcJRyvmfxqkhQ/8mJb2 # VVQrH4D6wPIOK+XW+6kvRBVK5xMOHds3OBqhK/bt1nz8MIIGsDCCBJigAwIBAgIQ # CK1AsmDSnEyfXs2pvZOu2TANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQGEwJVUzEV # MBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29t # MSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMjEwNDI5MDAw # MDAwWhcNMzYwNDI4MjM1OTU5WjBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGln # aUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29kZSBT # aWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExMIICIjANBgkqhkiG9w0BAQEF # AAOCAg8AMIICCgKCAgEA1bQvQtAorXi3XdU5WRuxiEL1M4zrPYGXcMW7xIUmMJ+k # jmjYXPXrNCQH4UtP03hD9BfXHtr50tVnGlJPDqFX/IiZwZHMgQM+TXAkZLON4gh9 # NH1MgFcSa0OamfLFOx/y78tHWhOmTLMBICXzENOLsvsI8IrgnQnAZaf6mIBJNYc9 # URnokCF4RS6hnyzhGMIazMXuk0lwQjKP+8bqHPNlaJGiTUyCEUhSaN4QvRRXXegY # E2XFf7JPhSxIpFaENdb5LpyqABXRN/4aBpTCfMjqGzLmysL0p6MDDnSlrzm2q2AS # 4+jWufcx4dyt5Big2MEjR0ezoQ9uo6ttmAaDG7dqZy3SvUQakhCBj7A7CdfHmzJa # wv9qYFSLScGT7eG0XOBv6yb5jNWy+TgQ5urOkfW+0/tvk2E0XLyTRSiDNipmKF+w # c86LJiUGsoPUXPYVGUztYuBeM/Lo6OwKp7ADK5GyNnm+960IHnWmZcy740hQ83eR # Gv7bUKJGyGFYmPV8AhY8gyitOYbs1LcNU9D4R+Z1MI3sMJN2FKZbS110YU0/EpF2 # 3r9Yy3IQKUHw1cVtJnZoEUETWJrcJisB9IlNWdt4z4FKPkBHX8mBUHOFECMhWWCK # ZFTBzCEa6DgZfGYczXg4RTCZT/9jT0y7qg0IU0F8WD1Hs/q27IwyCQLMbDwMVhEC # AwEAAaOCAVkwggFVMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFGg34Ou2 # O/hfEYb7/mF7CIhl9E5CMB8GA1UdIwQYMBaAFOzX44LScV1kTN8uZz/nupiuHA9P # MA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDAzB3BggrBgEFBQcB # AQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggr # BgEFBQcwAoY1aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1 # c3RlZFJvb3RHNC5jcnQwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybDMuZGln # aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcmwwHAYDVR0gBBUwEzAH # BgVngQwBAzAIBgZngQwBBAEwDQYJKoZIhvcNAQEMBQADggIBADojRD2NCHbuj7w6 # mdNW4AIapfhINPMstuZ0ZveUcrEAyq9sMCcTEp6QRJ9L/Z6jfCbVN7w6XUhtldU/ # SfQnuxaBRVD9nL22heB2fjdxyyL3WqqQz/WTauPrINHVUHmImoqKwba9oUgYftzY # gBoRGRjNYZmBVvbJ43bnxOQbX0P4PpT/djk9ntSZz0rdKOtfJqGVWEjVGv7XJz/9 # kNF2ht0csGBc8w2o7uCJob054ThO2m67Np375SFTWsPK6Wrxoj7bQ7gzyE84FJKZ # 9d3OVG3ZXQIUH0AzfAPilbLCIXVzUstG2MQ0HKKlS43Nb3Y3LIU/Gs4m6Ri+kAew # Q3+ViCCCcPDMyu/9KTVcH4k4Vfc3iosJocsL6TEa/y4ZXDlx4b6cpwoG1iZnt5Lm # Tl/eeqxJzy6kdJKt2zyknIYf48FWGysj/4+16oh7cGvmoLr9Oj9FpsToFpFSi0HA # SIRLlk2rREDjjfAVKM7t8RhWByovEMQMCGQ8M4+uKIw8y4+ICw2/O/TOHnuO77Xr # y7fwdxPm5yg/rBKupS8ibEH5glwVZsxsDsrFhsP2JjMMB0ug0wcCampAMEhLNKhR # ILutG4UI4lkNbcoFUCvqShyepf2gpx8GdOfy1lKQ/a+FSCH5Vzu0nAPthkX0tGFu # v2jiJmCG6sivqf6UHedjGzqGVnhOMIIGvDCCBKSgAwIBAgIQC65mvFq6f5WHxvnp # BOMzBDANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGln # aUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNBNDA5 # NiBTSEEyNTYgVGltZVN0YW1waW5nIENBMB4XDTI0MDkyNjAwMDAwMFoXDTM1MTEy # NTIzNTk1OVowQjELMAkGA1UEBhMCVVMxETAPBgNVBAoTCERpZ2lDZXJ0MSAwHgYD # VQQDExdEaWdpQ2VydCBUaW1lc3RhbXAgMjAyNDCCAiIwDQYJKoZIhvcNAQEBBQAD # ggIPADCCAgoCggIBAL5qc5/2lSGrljC6W23mWaO16P2RHxjEiDtqmeOlwf0KMCBD # Er4IxHRGd7+L660x5XltSVhhK64zi9CeC9B6lUdXM0s71EOcRe8+CEJp+3R2O8oo # 76EO7o5tLuslxdr9Qq82aKcpA9O//X6QE+AcaU/byaCagLD/GLoUb35SfWHh43rO # H3bpLEx7pZ7avVnpUVmPvkxT8c2a2yC0WMp8hMu60tZR0ChaV76Nhnj37DEYTX9R # eNZ8hIOYe4jl7/r419CvEYVIrH6sN00yx49boUuumF9i2T8UuKGn9966fR5X6kgX # j3o5WHhHVO+NBikDO0mlUh902wS/Eeh8F/UFaRp1z5SnROHwSJ+QQRZ1fisD8UTV # DSupWJNstVkiqLq+ISTdEjJKGjVfIcsgA4l9cbk8Smlzddh4EfvFrpVNnes4c16J # idj5XiPVdsn5n10jxmGpxoMc6iPkoaDhi6JjHd5ibfdp5uzIXp4P0wXkgNs+CO/C # acBqU0R4k+8h6gYldp4FCMgrXdKWfM4N0u25OEAuEa3JyidxW48jwBqIJqImd93N # Rxvd1aepSeNeREXAu2xUDEW8aqzFQDYmr9ZONuc2MhTMizchNULpUEoA6Vva7b1X # CB+1rxvbKmLqfY/M/SdV6mwWTyeVy5Z/JkvMFpnQy5wR14GJcv6dQ4aEKOX5AgMB # AAGjggGLMIIBhzAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUB # Af8EDDAKBggrBgEFBQcDCDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1s # BwEwHwYDVR0jBBgwFoAUuhbZbU2FL3MpdpovdYxqII+eyG8wHQYDVR0OBBYEFJ9X # LAN3DigVkGalY17uT5IfdqBbMFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwz # LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJTQTQwOTZTSEEyNTZUaW1l # U3RhbXBpbmdDQS5jcmwwgZAGCCsGAQUFBwEBBIGDMIGAMCQGCCsGAQUFBzABhhho # dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wWAYIKwYBBQUHMAKGTGh0dHA6Ly9jYWNl # cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJTQTQwOTZTSEEyNTZU # aW1lU3RhbXBpbmdDQS5jcnQwDQYJKoZIhvcNAQELBQADggIBAD2tHh92mVvjOIQS # R9lDkfYR25tOCB3RKE/P09x7gUsmXqt40ouRl3lj+8QioVYq3igpwrPvBmZdrlWB # b0HvqT00nFSXgmUrDKNSQqGTdpjHsPy+LaalTW0qVjvUBhcHzBMutB6HzeledbDC # zFzUy34VarPnvIWrqVogK0qM8gJhh/+qDEAIdO/KkYesLyTVOoJ4eTq7gj9UFAL1 # UruJKlTnCVaM2UeUUW/8z3fvjxhN6hdT98Vr2FYlCS7Mbb4Hv5swO+aAXxWUm3Wp # ByXtgVQxiBlTVYzqfLDbe9PpBKDBfk+rabTFDZXoUke7zPgtd7/fvWTlCs30VAGE # sshJmLbJ6ZbQ/xll/HjO9JbNVekBv2Tgem+mLptR7yIrpaidRJXrI+UzB6vAlk/8 # a1u7cIqV0yef4uaZFORNekUgQHTqddmsPCEIYQP7xGxZBIhdmm4bhYsVA6G2WgNF # YagLDBzpmk9104WQzYuVNsxyoVLObhx3RugaEGru+SojW4dHPoWrUhftNpFC5H7Q # EY7MhKRyrBe7ucykW7eaCuWBsBb4HOKRFVDcrZgdwaSIqMDiCLg4D+TPVgKx2EgE # deoHNHT9l3ZDBD+XgbF+23/zBjeCtxz+dL/9NWR6P2eZRi7zcEO1xwcdcqJsyz/J # ceENc2Sg8h3KeFUCS7tpFk7CrDqkMIIHXzCCBUegAwIBAgIQB8JSdCgUotar/iTq # F+XdLjANBgkqhkiG9w0BAQsFADBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGln # aUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29kZSBT # aWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExMB4XDTIzMDQxNjAwMDAwMFoX # DTI2MDcwNjIzNTk1OVowZzELMAkGA1UEBhMCUEwxEjAQBgNVBAcMCU1pa2/FgsOz # dzEhMB8GA1UECgwYUHJ6ZW15c8WCYXcgS8WCeXMgRVZPVEVDMSEwHwYDVQQDDBhQ # cnplbXlzxYJhdyBLxYJ5cyBFVk9URUMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw # ggIKAoICAQCUmgeXMQtIaKaSkKvbAt8GFZJ1ywOH8SwxlTus4McyrWmVOrRBVRQA # 8ApF9FaeobwmkZxvkxQTFLHKm+8knwomEUslca8CqSOI0YwELv5EwTVEh0C/Daeh # vxo6tkmNPF9/SP1KC3c0l1vO+M7vdNVGKQIQrhxq7EG0iezBZOAiukNdGVXRYOLn # 47V3qL5PwG/ou2alJ/vifIDad81qFb+QkUh02Jo24SMjWdKDytdrMXi0235CN4Rr # W+8gjfRJ+fKKjgMImbuceCsi9Iv1a66bUc9anAemObT4mF5U/yQBgAuAo3+jVB8w # iUd87kUQO0zJCF8vq2YrVOz8OJmMX8ggIsEEUZ3CZKD0hVc3dm7cWSAw8/FNzGNP # lAaIxzXX9qeD0EgaCLRkItA3t3eQW+IAXyS/9ZnnpFUoDvQGbK+Q4/bP0ib98XLf # QpxVGRu0cCV0Ng77DIkRF+IyR1PcwVAq+OzVU3vKeo25v/rntiXCmCxiW4oHYO28 # eSQ/eIAcnii+3uKDNZrI15P7VxDrkUIc6FtiSvOhwc3AzY+vEfivUkFKRqwvSSr4 # fCrrkk7z2Qe72Zwlw2EDRVHyy0fUVGO9QMuh6E3RwnJL96ip0alcmhKABGoIqSW0 # 5nXdCUbkXmhPCTT5naQDuZ1UkAXbZPShKjbPwzdXP2b8I9nQ89VSgQIDAQABo4IC # AzCCAf8wHwYDVR0jBBgwFoAUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHQYDVR0OBBYE # FHrxaiVZuDJxxEk15bLoMuFI5233MA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAK # BggrBgEFBQcDAzCBtQYDVR0fBIGtMIGqMFOgUaBPhk1odHRwOi8vY3JsMy5kaWdp # Y2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEz # ODQyMDIxQ0ExLmNybDBToFGgT4ZNaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0Rp # Z2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5j # cmwwPgYDVR0gBDcwNTAzBgZngQwBBAEwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3 # dy5kaWdpY2VydC5jb20vQ1BTMIGUBggrBgEFBQcBAQSBhzCBhDAkBggrBgEFBQcw # AYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFwGCCsGAQUFBzAChlBodHRwOi8v # Y2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmlu # Z1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNydDAJBgNVHRMEAjAAMA0GCSqGSIb3DQEB # CwUAA4ICAQC3EeHXUPhpe31K2DL43Hfh6qkvBHyR1RlD9lVIklcRCR50ZHzoWs6E # BlTFyohvkpclVCuRdQW33tS6vtKPOucpDDv4wsA+6zkJYI8fHouW6Tqa1W47YSrc # 5AOShIcJ9+NpNbKNGih3doSlcio2mUKCX5I/ZrzJBkQpJ0kYha/pUST2CbE3JroJ # f2vQWGUiI+J3LdiPNHmhO1l+zaQkSxv0cVDETMfQGZKKRVESZ6Fg61b0djvQSx51 # 0MdbxtKMjvS3ZtAytqnQHk1ipP+Rg+M5lFHrSkUlnpGa+f3nuQhxDb7N9E8hUVev # xALTrFifg8zhslVRH5/Df/CxlMKXC7op30/AyQsOQxHW1uNx3tG1DMgizpwBasrx # h6wa7iaA+Lp07q1I92eLhrYbtw3xC2vNIGdMdN7nd76yMIjdYnAn7r38wwtaJ3KY # D0QTl77EB8u/5cCs3ShZdDdyg4K7NoJl8iEHrbqtooAHOMLiJpiL2i9Yn8kQMB6/ # Q6RMO3IUPLuycB9o6DNiwQHf6Jt5oW7P09k5NxxBEmksxwNbmZvNQ65Zn3exUAKq # G+x31Egz5IZ4U/jPzRalElEIpS0rgrVg8R8pEOhd95mEzp5WERKFyXhe6nB6bSYH # v8clLAV0iMku308rpfjMiQkqS3LLzfUJ5OHqtKKQNMLxz9z185UCszGCBlMwggZP # AgEBMH0waTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMUEw # PwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IENvZGUgU2lnbmluZyBSU0E0MDk2 # IFNIQTM4NCAyMDIxIENBMQIQB8JSdCgUotar/iTqF+XdLjANBglghkgBZQMEAgEF # AKCBhDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgor # BgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3 # DQEJBDEiBCD2ZawQNZ4QYv4ZkcFO/o9F2bKYRr8ahnkiYRyOfeil6DANBgkqhkiG # 9w0BAQEFAASCAgAMZgXRRJJhnrkMGj1fb5srsL5o6jglFCLA90LPBur5HtPliTlO # uZ+LHVO7zXBdqnhxkebgFqi9oTswqe1XMlbM/CsI+Oga+nWC9aNluCclOGNdvVnH # DlNSJf+CMhzoMmT+87WE/4HxjVFP0kSTg6xXj7FwcRrvdwFJeYYYvbllMf+q0Bb1 # EJVmIZE+RYqt3X6Y4OhsaFvMwvJ7PBZCMAjfOkF7BxDYNJVUpdzQLhJ+1tUpfdOm # nLy43I2DeyDLiHdHLfotkObtjCVBFkt8Ov5ksvlhhtVTDQXddenoxGKfY2urGZ+5 # i1eb2YaHHdFyoD8d2Ohsh5SaB+j4+XNFx7Nl5fRTmhiSJ5lTpN0ZsMSEdGndytpY # v6H7E3uhna3Hfn2GbKBK6VYs0WEW+eyPhBWkZY9arIRZ72cGdaQVJTc2DBC5kRJB # upqQ7/oSL/3T7Edf/s3QuIzAe29yEuXMnIRJzE52tudN+EekQkY85l71psULVOqN # 3Rzn1h2jc7uKWBg5oUXede3UdKDyUux/gL0kpSgdeFubwfy4qXWQcLww0XoK3CKT # 8TocAqj7CXwWUlQVrvX27TKK7KPxQhLvcSA+eD98LR6/TGmD7hlgCmlyRDRfCobs # RojKp/KiLOL4sA+xENUQejtwJaIdOiymt4AoRc/FwkDMAnL8aKpLFjoDt6GCAyAw # ggMcBgkqhkiG9w0BCQYxggMNMIIDCQIBATB3MGMxCzAJBgNVBAYTAlVTMRcwFQYD # VQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBH # NCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0ECEAuuZrxaun+Vh8b56QTj # MwQwDQYJYIZIAWUDBAIBBQCgaTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwG # CSqGSIb3DQEJBTEPFw0yNDExMDUxNjExMDlaMC8GCSqGSIb3DQEJBDEiBCCmtYN7 # X0dqPAiu64pFnylWw0hiDXH5id+ZbWgEWDIy0zANBgkqhkiG9w0BAQEFAASCAgB3 # R1WnJPCShlwlZR264cSF5TCbmwnMHJ0zDWRUjEymaUl2g+iV51FJFfbX1rjQw6gB # ISMOC+oF3qgLuJRSOgwkyl+se5UU8jMtv7TrIPAF89d9DkNSJlWQWbTLIvZnHERg # PxEI0jT9zYr9hWSpEduT7k0GXDtVKS9Q6YXpwi7LIbQef3KxO2Unfm2WNkkmub9G # KEMlkyzx7qin7f0P1A168I5bqbjpDwBEl8OE0/DjcLNGosiAshk4eSIN9Hd2kzUL # pWF2kX9zEhMj5G/r/f0+564uaAyvd/G4c+g+n8JkFz7b+rh22lLZ8DAMF3SRhvtB # 97JjDsJq+mSSTMN2cUkpao1ERkpenEwsEzbQJ4akFxRBcXQ6MeITNW98lUFcpnSX # HPJmmvH4Xm7XZVB8umPIr3Tdc7yJizL3LB1nezxFQogTu1uJmRfZS7MduyuCSd+c # FIHlstfEKEjQi6/CwAVZQcr0JCqZJ5DdioWX8+uKAY/5nPxy07PBbH7UTLHAfvol # Xu/x9R8EcMwL9eFZ4bFFL0VY0iDXM2RYsutK6tRsXjGxdp8T/27ftNtyi3H+VtSB # zuPja/jo7+Woy7hZBsJy+B9kVz0arHt25NRblv2/Eyqsq+Pta7Xsr/4SbjQmoKen # mjumZzpZ12R1lhs9tbEe/ZbzPb2fZknCsBTZaMwveA== # SIG # End signature block |