public/Test-UcmO365ServicePlan.ps1
#PerformScriptSigning Function Test-UcmO365ServicePlan { <# .SYNOPSIS Checks the status of a specified Service Plan in Office365 .DESCRIPTION Cmdlet uses an existing Azure AD connection to filter through a users licences and check if the requested Service Plan is enabled. Handy for checking if an administrator has disabled Skype for Business Online before attempting to migrate them from Skype4B on prem, for example. .PARAMETER UPN The users username in UPN format .PARAMETER ServiceName Office365 Service Plan you wish to check .EXAMPLE PS> Test-UcmO365ServicePlan -UPN 'button.mash@contoso.com' -ServiceName 'MCOSTANDARD' Enables a user for Skype for Business Online (Required to migrate to Teams) .INPUTS User UPN - Users username in UPN format ServiceName - Office365 Service Plan you want to check .OUTPUT This Cmdet returns a PSCustomObject with multiple Keys to indicate status $Return.Status $Return.Message Return.Status can return one of four values "OK" : Service Plan is Enabled "Warning" : Service Plan is Disabled "Error" : Service Plan in an unknown state, like PendingProvisioning "Unknown" : Cmdlet reached the end of the fucntion without returning anything, this shouldnt happen, if it does please log an issue on Github Return.Message returns descriptive text based on the outcome, mainly for logging or reporting .NOTES Version: 1.1 Date: 03/04/2021 .VERSION HISTORY 1.1: Updated to "Ucm" naming convention Better inline documentation Updated PowerShell Verbage from Find to Test 1.0: Initial Public Release .REQUIRED FUNCTIONS/MODULES Modules AzureAD (Install-Module AzureAD) MSOnline (Install-Module MSOnline) UcmPSTools (Install-Module UcmPsTools) Includes Cmdlets below. Cmdlets Write-UcmLog: https://github.com/Atreidae/UcmPsTools/blob/main/public/Write-UcmLog.ps1 Test-UcmMSOLConnection https://github.com/Atreidae/UcmPsTools/blob/main/public/Test-UcmMSOLConnection.ps1 New-UcmMSOLConnection https://github.com/Atreidae/UcmPsTools/blob/main/public/New-UcmMSOLConnection.ps1 .REQUIRED PERMISIONS 'Office365 User Admin' or better .LINK http://www.UcMadScientist.com https://github.com/Atreidae/UcmPsTools .ACKNOWLEDGEMENTS #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseProcessBlockForPipelineCommand', '', Scope='Function')] #todo, https://github.com/Atreidae/UcmPSTools/issues/23 Param ( [Parameter(ValueFromPipelineByPropertyName=$true, Mandatory, Position=1,HelpMessage='The UPN of the user you wish to check the Service Plan on, eg: button.mash@contoso.com')] [string]$UPN, [Parameter(ValueFromPipelineByPropertyName=$true, Mandatory, Position=2,HelpMessage="The name of the Office365 Service Plan you wish check the status of, eg: 'MCOSTANDARD' for Skype Online")] [string]$ServiceName ) #region FunctionSetup, Set Default Variables for HTML Reporting and Write Log $function = 'Test-UcmO365ServicePlan' [hashtable]$Return = @{} $return.Function = $function $return.Status = 'Unknown' $return.Message = 'Function did not return a status message' # Log why we were called Write-UcmLog -Message "$($MyInvocation.InvocationName) called with $($MyInvocation.Line)" -Severity 1 -Component $function Write-UcmLog -Message 'Parameters' -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$($PsBoundParameters.Keys)" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message 'Parameters Values' -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$($PsBoundParameters.Values)" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message 'Optional Arguments' -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$Args" -Severity 1 -Component $function -LogOnly #endregion FunctionSetup #region FunctionWork #Check to see if we are connected to MSOL $Test = (Test-UcmMSOLConnection -Reconnect) If ($Test.Status -ne "OK") { #MSOL check failed, return an error. Write-UcmLog -Message "Something went wrong checking $UPN's service plans" -Severity 3 -Component $function Write-UcmLog -Message "Test-UcmMSOLConnection could not locate an MSOL connection" -Severity 2 -Component $function $Return.Status = "Error" $Return.Message = "No MSOL Connection" Return $Return } #Set a flag to see if the licence is enabled $Enabled =$false #Get the users licences and enumerate through them looking for the relevant service plan $LicenseDetails = (Get-MsolUser -UserPrincipalName $UPN).Licenses ForEach ($License in $LicenseDetails) { #check the relevant service plans on this licence. ForEach ($ServiceStatus in $License.ServiceStatus) { #check to see if the service name matches the requested name and its status If ($ServiceStatus.ProvisioningStatus -eq 'Disabled' -and $_.ServicePlan.ServiceName -eq "$serviceName") { #Found the service plan, and its disabled, $Enabled is already $False, no need to set anything. Write-UcmLog -Message "$ServiceName Disabled" -Severity 2 -Component $function } Elseif ($ServiceStatus.ProvisioningStatus -eq 'Success' -and $_.ServicePlan.ServiceName -eq "$serviceName") { #Found the service plan, and its provisioned, Set the Enabled flag to true Write-UcmLog -Message "$ServiceName Enabled" -Severity 2 -Component $function $Enabled = $true } ElseIf ($ServiceStatus.ServicePlan.ServiceName -like "*$serviceName*") { #Found the service plan, and its not provisioned properly, this could be to a service issue or a multitude of other reasons (IE, MCOEV will error if the LineURI is already assigned). return an error Write-UcmLog -Message "$ServiceName is in unknown state , you may need to run '(Get-MsolUser -UserPrincipalName $UPN).Licenses' for more information" -Severity 3 -Component $function $Enabled = 'Error' } } #End Service Plan Status Loop }#End licence loop If ($enabled -eq 'Error') { #Encounted an error with Service Plan, return an error. Write-UcmLog -Message "$ServiceName is in unknown state" -Severity 2 -Component $function $Return.Status = 'ERROR' $Return.Message = "$ServiceName is in unknown state, you may need to run '(Get-MsolUser -UserPrincipalName $UPN).Licenses' for more information" Return $Return } Elseif ($enabled -eq $true) { #The ServicePlan is enabled, return OK Write-UcmLog -Message "$ServiceName Enabled" -Severity 2 -Component $function $Return.Status = 'OK' $Return.Message = "$ServiceName Enabled" Return $Return } ElseIf ($_.ServicePlan.ServiceName -like "*$serviceName*") { #The ServicePlan is disabled, return a warning Write-UcmLog -Message "$ServiceName Disabled" -Severity 2 -Component $function $Return.Status = 'Warning' $Return.Message = "$ServiceName Disabled" Return $Return } #endregion FunctionWork #region FunctionReturn #Default Return Variable for my HTML Reporting Fucntion Write-UcmLog -Message "Reached end of $function without a Return Statement" -Severity 3 -Component $function $return.Status = 'Unknown' $return.Message = 'Function did not encounter return statement' Return $Return #endregion FunctionReturn } # SIG # Begin signature block # MIIRwgYJKoZIhvcNAQcCoIIRszCCEa8CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUPQ9BL4Tlr/CSXqC7peL49TRa # +EOggg4OMIIGsDCCBJigAwIBAgIQCK1AsmDSnEyfXs2pvZOu2TANBgkqhkiG9w0B # AQwFADBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVk # IFJvb3QgRzQwHhcNMjEwNDI5MDAwMDAwWhcNMzYwNDI4MjM1OTU5WjBpMQswCQYD # VQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lD # ZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEg # Q0ExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1bQvQtAorXi3XdU5 # WRuxiEL1M4zrPYGXcMW7xIUmMJ+kjmjYXPXrNCQH4UtP03hD9BfXHtr50tVnGlJP # DqFX/IiZwZHMgQM+TXAkZLON4gh9NH1MgFcSa0OamfLFOx/y78tHWhOmTLMBICXz # ENOLsvsI8IrgnQnAZaf6mIBJNYc9URnokCF4RS6hnyzhGMIazMXuk0lwQjKP+8bq # HPNlaJGiTUyCEUhSaN4QvRRXXegYE2XFf7JPhSxIpFaENdb5LpyqABXRN/4aBpTC # fMjqGzLmysL0p6MDDnSlrzm2q2AS4+jWufcx4dyt5Big2MEjR0ezoQ9uo6ttmAaD # G7dqZy3SvUQakhCBj7A7CdfHmzJawv9qYFSLScGT7eG0XOBv6yb5jNWy+TgQ5urO # kfW+0/tvk2E0XLyTRSiDNipmKF+wc86LJiUGsoPUXPYVGUztYuBeM/Lo6OwKp7AD # K5GyNnm+960IHnWmZcy740hQ83eRGv7bUKJGyGFYmPV8AhY8gyitOYbs1LcNU9D4 # R+Z1MI3sMJN2FKZbS110YU0/EpF23r9Yy3IQKUHw1cVtJnZoEUETWJrcJisB9IlN # Wdt4z4FKPkBHX8mBUHOFECMhWWCKZFTBzCEa6DgZfGYczXg4RTCZT/9jT0y7qg0I # U0F8WD1Hs/q27IwyCQLMbDwMVhECAwEAAaOCAVkwggFVMBIGA1UdEwEB/wQIMAYB # Af8CAQAwHQYDVR0OBBYEFGg34Ou2O/hfEYb7/mF7CIhl9E5CMB8GA1UdIwQYMBaA # FOzX44LScV1kTN8uZz/nupiuHA9PMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAK # BggrBgEFBQcDAzB3BggrBgEFBQcBAQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9v # Y3NwLmRpZ2ljZXJ0LmNvbTBBBggrBgEFBQcwAoY1aHR0cDovL2NhY2VydHMuZGln # aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcnQwQwYDVR0fBDwwOjA4 # oDagNIYyaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJv # b3RHNC5jcmwwHAYDVR0gBBUwEzAHBgVngQwBAzAIBgZngQwBBAEwDQYJKoZIhvcN # AQEMBQADggIBADojRD2NCHbuj7w6mdNW4AIapfhINPMstuZ0ZveUcrEAyq9sMCcT # Ep6QRJ9L/Z6jfCbVN7w6XUhtldU/SfQnuxaBRVD9nL22heB2fjdxyyL3WqqQz/WT # auPrINHVUHmImoqKwba9oUgYftzYgBoRGRjNYZmBVvbJ43bnxOQbX0P4PpT/djk9 # ntSZz0rdKOtfJqGVWEjVGv7XJz/9kNF2ht0csGBc8w2o7uCJob054ThO2m67Np37 # 5SFTWsPK6Wrxoj7bQ7gzyE84FJKZ9d3OVG3ZXQIUH0AzfAPilbLCIXVzUstG2MQ0 # HKKlS43Nb3Y3LIU/Gs4m6Ri+kAewQ3+ViCCCcPDMyu/9KTVcH4k4Vfc3iosJocsL # 6TEa/y4ZXDlx4b6cpwoG1iZnt5LmTl/eeqxJzy6kdJKt2zyknIYf48FWGysj/4+1 # 6oh7cGvmoLr9Oj9FpsToFpFSi0HASIRLlk2rREDjjfAVKM7t8RhWByovEMQMCGQ8 # M4+uKIw8y4+ICw2/O/TOHnuO77Xry7fwdxPm5yg/rBKupS8ibEH5glwVZsxsDsrF # hsP2JjMMB0ug0wcCampAMEhLNKhRILutG4UI4lkNbcoFUCvqShyepf2gpx8GdOfy # 1lKQ/a+FSCH5Vzu0nAPthkX0tGFuv2jiJmCG6sivqf6UHedjGzqGVnhOMIIHVjCC # BT6gAwIBAgIQDyLHeeRvkUFg5QtSFTT8FjANBgkqhkiG9w0BAQsFADBpMQswCQYD # VQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lD # ZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEg # Q0ExMB4XDTIzMDIyMzAwMDAwMFoXDTI2MDIyMzIzNTk1OVowXjELMAkGA1UEBhMC # QVUxETAPBgNVBAgTCFZpY3RvcmlhMRAwDgYDVQQHEwdCZXJ3aWNrMRQwEgYDVQQK # EwtKYW1lcyBBcmJlcjEUMBIGA1UEAxMLSmFtZXMgQXJiZXIwggIiMA0GCSqGSIb3 # DQEBAQUAA4ICDwAwggIKAoICAQC47oExh25TrxvApIYdMRYvjOdZCb8WwgeTemm3 # ZY7BElIWu6+gzRGqQe8RFsN7oIgin5pvjTYIToxt1CCag2A5o8L0NtULmxJEegc+ # VaF24DZQqI4qGQGH/Qnglqys6+yPkwLnfeSxpeWe4u49HUUGDFIxHCh42MlCLp/f # fHT49QhhpO+LyeLnDoUs6DmahyIb6NeE2cW5AYRXEesW7GRNfXzygBSlVWJOgvcy # V5Y4IvAZVx2hKKMTjYFIz4/RYMg7fwYZEJ2LRJ/GnVazobKAvh6ZBet5KwVNI9EI # 29DtWQyK/RoPOguTRcB5VuiZVlv0xjBYM7iJuH2Soa3StQYVxL/5gjZCC9WOs4NR # EIGU3XmHoogFDvoT1vf1izMPFQzdZfgPvy/XXsbgTVo5ncesJ6WtZwqwCXG1K0XW # IPZqTHolc1MyU6K1bEHO+7YWLpKgM9THl644G7PEhcKpNDsHlfvLVQdYhI55UJtc # iyMrTw11CNECvk3GK1mrluvKsrxdaH6G3Sp9VVHRtef6OZ5SlzkM5ID4egB2bXRb # R/69bEuZr5hhm+v2lBSWIbZj/Mva6i/a/TAvy4vvPLo3DRcASkYZDC4T8gDMzmpG # Xs4jAc9sfTL9z+o5u1PLJHFGRjJ+Wa2CgSftCdbKLjn+AY9m8ipc8jmOBKNY9yGI # pQWapQIDAQABo4ICAzCCAf8wHwYDVR0jBBgwFoAUaDfg67Y7+F8Rhvv+YXsIiGX0 # TkIwHQYDVR0OBBYEFOBsg1xudlbXVSql8pWbiHoTyZS/MA4GA1UdDwEB/wQEAwIH # gDATBgNVHSUEDDAKBggrBgEFBQcDAzCBtQYDVR0fBIGtMIGqMFOgUaBPhk1odHRw # Oi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmlu # Z1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNybDBToFGgT4ZNaHR0cDovL2NybDQuZGln # aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hB # Mzg0MjAyMUNBMS5jcmwwPgYDVR0gBDcwNTAzBgZngQwBBAEwKTAnBggrBgEFBQcC # ARYbaHR0cDovL3d3dy5kaWdpY2VydC5jb20vQ1BTMIGUBggrBgEFBQcBAQSBhzCB # hDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFwGCCsGAQUF # BzAChlBodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVk # RzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNydDAJBgNVHRMEAjAA # MA0GCSqGSIb3DQEBCwUAA4ICAQBOh5vRXqTCQzv0T1F2EgDkq5VnljlHsa7Ov/d/ # lpOvr8NebBiatxbhfhPCnToY7BD2f7YVsUuQ+VDdcIYsskcU5spBHcFYidg2jGu4 # 59FGMaS765XStDwGGTN/360gEsNYSnKWYL4+8jYWHlzRO0jHloyWz+gF5dYWzdDJ # u1dudLIJ0RgrEVJeLSgIBWygLL5EyIzOPlrxztsILMSbdPTQLeBIm7ipOk4EACx1 # hhBVUsUoCAlASH+yCKDU4v2HFd7SzrkRUrf7XJ2Na2YsiHjiTGqHIE86KyvxGDhT # 3n2/jX23Nh/bkWHurHwTfaTCOQ44ZlAbnZQjBlmrFn5hPMXRpciiQFmrKTPD/nuo # 9MVnCciHEpHJ63/JZNF/eno1122/wVkL7MuRlCVHN7L/wuNQxQk3ARdIju6OD/Gi # Mwg0Qih6HVWJtkHK3ExoUKKKUZCOvIeHxzp+K6FWUupPZKUgWzn4AHMxm6zr+Sde # laIAACqAkxYsDYKbM7WlNi3uIH2HeXqU9uSDt5tgPpImrog/ab4HrhpDfITRgT1c # cxaWQezpJEPC+kqVD41T3wlEie1Qm4vYWg+oBVEMBxVLh6CYbeppCRTEXRGnAiCH # /Ma1uwyWnNCWxrhd1uSi6sj4ISzgnFyGCvsI0gavKpS5AQhapJgk6/fULTFeS+Ee # kRH9FDGCAx4wggMaAgEBMH0waTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lD # ZXJ0LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IENvZGUgU2ln # bmluZyBSU0E0MDk2IFNIQTM4NCAyMDIxIENBMQIQDyLHeeRvkUFg5QtSFTT8FjAJ # BgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkqhkiG9w0B # CQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAj # BgkqhkiG9w0BCQQxFgQUSon13bKq5yeajFpfVpKJbX6iT8cwDQYJKoZIhvcNAQEB # BQAEggIAGa1CHRdEVsW6kszPeaA5yjJpDEmU8EWtI8D1uYOUaGy9NifnA30FrDFX # Jj+asWLVkeSqzHW91pE9LlvEJZUHIjbhTivq6i50UD79o/6tmUGFtgWT+TPfnqpJ # Bb7vPQtaweagu4aX6ock+l2t83wDgxV+yDA9w49VgffL23X4SNAZnttaYBkSVWQS # 30sI5U1fQrIwOpkLP77i0Zw0SHY73N3d+JEeMAgKYooVVhNOY9xlH+ZVw2ffN2tY # iHfJceF9XXmw3vLWoVDsc9PFY2mDodaX6ABR7XcksqNlbeMzEHH+9xxtUKa3uaX5 # LoI1/2SDiIyuAxll8B2degDJggRLE0ycdh7rgFGVg6exgfitVIhW6yyujcx2Al4H # hG+/cxYI1hDFsljTt/qZzUeUxOEUtWloz1GNzn/aU3gdu55ONM2g9Q6o53Qzsgx6 # GFfhZIUedkPF0RGMGJyNSRYeNrOk3ncU5EYIgezwr82m+83ay0778dwQJ799e1rg # ERPadyx/ZXvd4FyFmzPE9bhUGdM1774s1Ypf/rD1eGIXs2AUdLvUHoekDevFKeQ9 # r6n7U7UosREi1ffA+CdOmdS1XmtLANrmY5hXp8LmVUXBtMpAyg9yNqcp93v9XDun # 2Ls0d4K1K2HNpxOaU2cu1N76kIKOU0phYuW8op9s+dcO8eOSgDE= # SIG # End signature block |