Find-MsIdUnprotectedUsersWithAdminRoles.ps1
<# .SYNOPSIS Find Users with Admin Roles that are not registered for MFA .DESCRIPTION Find Users with Admin Roles that are not registered for MFA by evaluating their authentication methods registered for MFA and their sign-in activity. .EXAMPLE PS > Find-MsIdUnprotectedUsersWithAdminRoles Enumerate users with role assignments .EXAMPLE PS > Find-MsIdUnprotectedUsersWithAdminRoles -includeSignIns:$false Enumerate users with role assignments including their sign in activity .NOTES - Eligible users for roles may not have active assignments showing in their directoryrolememberships, but they have the potential to elevate to assigned roles - Large amounts of role assignments may take time process. - Must be connected to MS Graph with appropriate scopes for reading user, group, application, role, an sign in information and selected the beta profile before running. -- Connect-MgGraph -scopes RoleManagement.Read.Directory,UserAuthenticationMethod.Read.All,AuditLog.Read.All,User.Read.All,Group.Read.All,Application.Read.All -- Select-MgProfile -name Beta #> function Find-MsIdUnprotectedUsersWithAdminRoles { [CmdletBinding()] [OutputType([string])] param ( # Include Sign In log activity - Note this can cause the query to run slower in larger active environments [switch] $IncludeSignIns ) begin { ## Initialize Critical Dependencies $CriticalError = $null if (!(Test-MgCommandPrerequisites 'Get-MgUser', 'Get-MgUserAuthenticationMethod', 'Get-MgGroupMember', 'Get-MgRoleManagementDirectoryRoleDefinition', 'Get-MgRoleManagementDirectoryRoleAssignmentSchedule', 'Get-MgRoleManagementDirectoryRoleEligibilitySchedule', 'Get-MgAuditLogSignIn' -ApiVersion beta -MinimumVersion 1.9.2 -RequireListPermissions -ErrorVariable CriticalError)) { return } ## Save Current MgProfile to Restore at End $previousMgProfile = Get-MgProfile if ($previousMgProfile.Name -ne 'beta') { Select-MgProfile -Name 'beta' -Verbose:$false # -Verbose:$false is not suppressing output } if ($VerbosePreference -eq 'SilentlyContinue') { Write-Host "NOTE: This process may take awhile depending on the size of the environment. Please run with -Verbose switch for more details progress output." } } process { if ($CriticalError) { return } [array]$usersWithRoles = Get-UsersWithRoleAssignments $TotalUsersCount = $usersWithRoles.count Write-Verbose ("Checking {0} users with roles..." -f $TotalUsersCount) [array]$checkedUsers = @() $checkUsersCount = 0 foreach ($user in $usersWithRoles) { $checkUsersCount++ $userObject = $null try { $userObject = Get-MgUser -UserId $user.PrincipalId -Property signInActivity, UserPrincipalName, Id } catch { Write-Warning ("User object with UserId {0} with a role assignment was not found! Review assignment for orphaned user." -f $user.PrincipalId) } Write-Verbose ("User {0} of {1} - Evaluating {2} with role assignments...." -f $checkUsersCount, $TotalUsersCount, $userObject.Id) if ($Null -ne $userObject) { $UserAuthMethodStatus = Get-UserMfaRegisteredStatus -UserId $userObject.UserPrincipalName $checkedUser = [ordered] @{} $checkedUser.UserID = $userObject.Id $checkedUser.UserPrincipalName = $userObject.UserPrincipalName If ($null -eq $userObject.signInActivity.LastSignInDateTime) { $checkedUser.LastSignInDateTime = "Unknown" $checkedUser.LastSigninDaysAgo = "Unknown" } else { $checkedUser.LastSignInDateTime = $userObject.signInActivity.LastSignInDateTime $checkedUser.LastSigninDaysAgo = (New-TimeSpan -Start $checkedUser.LastSignInDateTime -End (Get-Date)).Days } $checkedUser.DirectoryRoleAssignments = $user.RoleName $checkedUser.DirectoryRoleAssignmentType = $user.AssignmentType $checkedUser.DirectoryRoleAssignmentCount = $user.RoleName.count $checkedUser.RoleAssignedBy = $user.RoleAssignedBy $checkedUser.IsMfaRegistered = $UserAuthMethodStatus.isMfaRegistered $checkedUser.Status = $UserAuthMethodStatus.Status if ($includeSignIns -eq $true) { $signInInfo = Get-UserSignInSuccessHistoryAuth -userId $checkedUser.UserId $checkedUser.SuccessSignIns = $signInInfo.SuccessSignIns $checkedUser.MultiFactorSignIns = $signInInfo.MultiFactorSignIns $checkedUser.SingleFactorSignIns = $signInInfo.SingleFactorSignIns $checkedUser.RiskySignIns = $signInInfo.RiskySignIns } else { $checkedUser.SuccessSignIns = "Skipped" $checkedUser.MultiFactorSignIns = "Skipped" $checkedUser.SingleFactorSignIns = "Skipped" $checkedUser.RiskySignIns = "Skipped" } $checkedUsers += ([pscustomobject]$checkedUser) } else { $checkedUser = [ordered] @{} $checkedUser.UserID = $userObject.Id $checkedUser.Status = "Not Exists" } } } end { if ($CriticalError) { return } Write-Verbose ("{0} Users Evaluated!" -f $checkedUsers.count) Write-Verbose ("{0} Users with roles who are NOT registered for MFA!" -f ($checkedUsers | Where-Object -FilterScript { $_.isMfaRegistered -eq $false }).count) Write-Output $checkedUsers ## Restore Previous MgProfile if ($previousMgProfile -and $previousMgProfile.Name -ne (Get-MgProfile).Name) { Select-MgProfile -Name $previousMgProfile.Name -Verbose:$false # -Verbose:$false is not suppressing output } } } function Get-UserMfaRegisteredStatus ([string]$UserId) { $mfaMethods = @("#microsoft.graph.fido2AuthenticationMethod", "#microsoft.graph.softwareOathAuthenticationMethod", "#microsoft.graph.microsoftAuthenticatorAuthenticationMethod", "#microsoft.graph.windowsHelloForBusinessAuthenticationMethod", "#microsoft.graph.phoneAuthenticationMethod") $results = [pscustomobject]@{ IsMfaRegistered = $null AuthMethodsRegistered = $null status = $null } try { $authMethods = (Get-MgUserAuthenticationMethod -UserId $UserId).AdditionalProperties."@odata.type" $isMfaRegistered = $false foreach ($mfa in $MfaMethods) { if ($authmethods -contains $mfa) { $isMfaRegistered = $true } } $results.IsMfaRegistered = $isMfaRegistered $results.AuthMethodsRegistered = $authMethods $results.status = "Checked" } catch { $results.status = "Unknown" } Write-Output $results } function Get-UserSignInSuccessHistoryAuth ([string]$userId) { $signinAuth = @{} $signinAuth.UserID = $userId $signinAuth.SuccessSignIns = 0 $signinAuth.MultiFactorSignIns = 0 $signinAuth.SingleFactorSignIns = 0 $signInAuth.RiskySignIns = 0 $filter = ("UserId eq '{0}' and status/errorCode eq 0" -f $userId) Write-Debug $filter [array]$signins = Get-MgAuditLogSignIn -Filter $filter -all:$True Write-Debug $signins.count if ($signins.count -gt 0) { $signinAuth.SuccessSignIns = $signins.count $groupedAuth = $signins | Group-Object -Property AuthenticationRequirement $MfaSignInsCount = 0 $MfaSignInsCount = $groupedAuth | Where-Object -FilterScript { $_.Name -eq 'multiFactorAuthentication' } | Select-Object -ExpandProperty count if ($null -eq $MfaSignInsCount) { $MfaSignInsCount = 0 } $signinAuth.MultiFactorSignIns = $MfaSignInsCount $singleFactorSignInsCount = 0 $singleFactorSignInsCount = $groupedAuth | Where-Object -FilterScript { $_.Name -eq 'singleFactorAuthentication' } | Select-Object -ExpandProperty count if ($null -eq $singleFactorSignInsCount) { $singleFactorSignInsCount = 0 } $signinAuth.SingleFactorSignIns = $singleFactorSignInsCount $signInAuth.RiskySignIns = ($signins | Where-Object -FilterScript { $_.RiskLevelDuringSignIn -ne 'none' } | Measure-Object | Select-Object -ExpandProperty Count) } Write-Output ([pscustomobject]$signinAuth) } function Get-UsersWithRoleAssignments() { [array]$uniquePrincipals = $null [array]$usersWithRoles = $Null [array]$groupsWithRoles = $null [array]$servicePrincipalsWithRoles = $null [array]$roleAssignments = @() [array]$activeRoleAssignments = $null [array]$eligibleRoleAssignments = $null [array]$AssignmentSchedule = @() Write-Verbose "Retrieving Active Role Assignments..." [array]$activeRoleAssignments = Get-MgRoleManagementDirectoryRoleAssignmentSchedule -All:$true -ExpandProperty Principal | Add-Member -MemberType NoteProperty -Name AssignmentScope -Value "Active" -Force -PassThru | Add-Member -MemberType ScriptProperty -Name PrincipalType -Value { $this.Principal.AdditionalProperties."@odata.type".split('.')[2] } -Force -PassThru Write-Verbose ("{0} Active Role Assignments..." -f $activeRoleAssignments.count) $AssignmentSchedule += $activeRoleAssignments Write-Verbose "Retrieving Eligible Role Assignments..." [array]$eligibleRoleAssignments = Get-MgRoleManagementDirectoryRoleEligibilitySchedule -All:$true -ExpandProperty Principal | Add-Member -MemberType NoteProperty -Name AssignmentScope -Value "Eligible" -Force -PassThru | Add-Member -MemberType ScriptProperty -Name PrincipalType -Value { $this.Principal.AdditionalProperties."@odata.type".split('.')[2] } -Force -PassThru Write-Verbose ("{0} Eligible Role Assignments..." -f $eligibleRoleAssignments.count) $AssignmentSchedule += $eligibleRoleAssignments Write-Verbose ("{0} Total Role Assignments to all principals..." -f $AssignmentSchedule.count) [array]$uniquePrincipals = $AssignmentSchedule.PrincipalId | Get-Unique Write-Verbose ("{0} Total Role Assignments to unique principals..." -f $uniquePrincipals.count) foreach ($type in ($AssignmentSchedule | Group-Object PrincipalType)) { Write-Verbose ("{0} assignments to {1} type" -f $type.count, $type.name) } foreach ($assignment in ($AssignmentSchedule)) { if ($assignment.PrincipalType -eq 'user') { $roleAssignment = @{} $roleAssignment.PrincipalId = $assignment.PrincipalId $roleAssignment.PrincipalType = $assignment.PrincipalType $roleAssignment.AssignmentType = $assignment.AssignmentScope $roleAssignment.RoleDefinitionId = $assignment.RoleDefinitionId $roleAssignment.RoleAssignedBy = "user" $roleAssignment.RoleName = [array](Get-MgRoleManagementDirectoryRoleDefinition -UnifiedRoleDefinitionId $assignment.RoleDefinitionId | Select-Object -ExpandProperty displayName) $roleAssignments += ([pscustomobject]$roleAssignment) } if ($assignment.PrincipalType -eq 'group') { Write-Verbose ("Expanding Group Members for Role Assignable Group {0}" -f $assignment.PrincipalId) $groupMembers = Get-MgGroupMember -GroupId $assignment.PrincipalId | Select-Object -ExpandProperty Id [array]$RoleName = Get-MgRoleManagementDirectoryRoleDefinition -UnifiedRoleDefinitionId $assignment.RoleDefinitionId | Select-Object -ExpandProperty displayName foreach ($member in $groupMembers) { Write-Verbose ("Adding Group Member {0} for Role Assignable Group {0}" -f $member, $assignment.PrincipalId) $roleAssignment = @{} $roleAssignment.PrincipalId = $member $roleAssignment.PrincipalType = "user" $roleAssignment.AssignmentType = $assignment.AssignmentScope $roleAssignment.RoleDefinitionId = $assignment.RoleDefinitionId $roleAssignment.RoleAssignedBy = "group" $roleAssignment.RoleName = $RoleName $roleAssignments += ([pscustomobject]$roleAssignment) } } } [array]$usersWithRoles = $roleAssignments | Where-Object -FilterScript { $_.PrincipalType -eq 'user' } Write-Verbose ("{0} Total Role Assignments to Users" -f $usersWithRoles.count) Write-Output $usersWithRoles } # SIG # Begin signature block # MIInqgYJKoZIhvcNAQcCoIInmzCCJ5cCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCA7KRmX/EFZcCDc # he1n16Iks0vVht0lUYkZAVBLl5WmRaCCDYEwggX/MIID56ADAgECAhMzAAACzI61 # lqa90clOAAAAAALMMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjIwNTEyMjA0NjAxWhcNMjMwNTExMjA0NjAxWjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQCiTbHs68bADvNud97NzcdP0zh0mRr4VpDv68KobjQFybVAuVgiINf9aG2zQtWK # No6+2X2Ix65KGcBXuZyEi0oBUAAGnIe5O5q/Y0Ij0WwDyMWaVad2Te4r1Eic3HWH # UfiiNjF0ETHKg3qa7DCyUqwsR9q5SaXuHlYCwM+m59Nl3jKnYnKLLfzhl13wImV9 # DF8N76ANkRyK6BYoc9I6hHF2MCTQYWbQ4fXgzKhgzj4zeabWgfu+ZJCiFLkogvc0 # RVb0x3DtyxMbl/3e45Eu+sn/x6EVwbJZVvtQYcmdGF1yAYht+JnNmWwAxL8MgHMz # xEcoY1Q1JtstiY3+u3ulGMvhAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUiLhHjTKWzIqVIp+sM2rOHH11rfQw # UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1 # ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDcwNTI5MB8GA1UdIwQYMBaAFEhu # ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu # bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w # Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3 # Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx # MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAeA8D # sOAHS53MTIHYu8bbXrO6yQtRD6JfyMWeXaLu3Nc8PDnFc1efYq/F3MGx/aiwNbcs # J2MU7BKNWTP5JQVBA2GNIeR3mScXqnOsv1XqXPvZeISDVWLaBQzceItdIwgo6B13 # vxlkkSYMvB0Dr3Yw7/W9U4Wk5K/RDOnIGvmKqKi3AwyxlV1mpefy729FKaWT7edB # d3I4+hldMY8sdfDPjWRtJzjMjXZs41OUOwtHccPazjjC7KndzvZHx/0VWL8n0NT/ # 404vftnXKifMZkS4p2sB3oK+6kCcsyWsgS/3eYGw1Fe4MOnin1RhgrW1rHPODJTG # AUOmW4wc3Q6KKr2zve7sMDZe9tfylonPwhk971rX8qGw6LkrGFv31IJeJSe/aUbG # dUDPkbrABbVvPElgoj5eP3REqx5jdfkQw7tOdWkhn0jDUh2uQen9Atj3RkJyHuR0 # GUsJVMWFJdkIO/gFwzoOGlHNsmxvpANV86/1qgb1oZXdrURpzJp53MsDaBY/pxOc # J0Cvg6uWs3kQWgKk5aBzvsX95BzdItHTpVMtVPW4q41XEvbFmUP1n6oL5rdNdrTM # j/HXMRk1KCksax1Vxo3qv+13cCsZAaQNaIAvt5LvkshZkDZIP//0Hnq7NnWeYR3z # 4oFiw9N2n3bb9baQWuWPswG0Dq9YT9kb+Cs4qIIwggd6MIIFYqADAgECAgphDpDS # AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 # IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0 # ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla # MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT # H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB # AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG # OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S # 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz # y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7 # 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u # M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33 # X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl # XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP # 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB # l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF # RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM # CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ # BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud # DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO # 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0 # LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y # Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p # Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y # Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB # FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw # cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA # XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY # 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj # 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd # d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ # Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf # wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ # aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j # NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B # xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96 # eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7 # r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I # RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIZfzCCGXsCAQEwgZUwfjELMAkG # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z # b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAsyOtZamvdHJTgAAAAACzDAN # BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor # BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgwQPKwEH9 # tJkoQkMiC2WDRBwt2lv7Eo04dAQ3/Tb8wIgwQgYKKwYBBAGCNwIBDDE0MDKgFIAS # AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN # BgkqhkiG9w0BAQEFAASCAQAczwx0g/bogUA/PqHAIyxfV1ImkwlNKA/g3lVsAOzN # OcyCWfmGFhbw1w+Kd2c9WJpizcS105h3sLKGBF0tM+O9QG3rOEBPiEdbv6PjeC1v # d0L7pfcCPS/BubjdVvuRuWt50rqueEntZysljw/VlcleeKXdrhAwt98B4qExIsDs # 8IZfnTbRKbwFVDhIjdfDy8QbTq6nwPr67tlSSD3aJMvb8ny9LGtETme/qMGVeNz6 # LP1WthjFcLCWTI07JiHH1Dagkb+nUIqOchsnvokFH49snorxYIXBGWavp5Q65p85 # HnVuWg+2LTe52ruy4HbIoQa+at1B9gMdDSaR6qlce9sHoYIXCTCCFwUGCisGAQQB # gjcDAwExghb1MIIW8QYJKoZIhvcNAQcCoIIW4jCCFt4CAQMxDzANBglghkgBZQME # AgEFADCCAVUGCyqGSIb3DQEJEAEEoIIBRASCAUAwggE8AgEBBgorBgEEAYRZCgMB # MDEwDQYJYIZIAWUDBAIBBQAEIPF+tpxdYsnZp5nbClAx+fOgZMuXFFJVQIO8Fscx # ygX5AgZjxortyx4YEzIwMjMwMTI4MDIyNjU0LjYxOVowBIACAfSggdSkgdEwgc4x # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1p # Y3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMg # VFNTIEVTTjpGNzdGLUUzNTYtNUJBRTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt # U3RhbXAgU2VydmljZaCCEVwwggcQMIIE+KADAgECAhMzAAABqqUxmwvLsggOAAEA # AAGqMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo # aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y # cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw # MB4XDTIyMDMwMjE4NTEyNloXDTIzMDUxMTE4NTEyNlowgc4xCzAJBgNVBAYTAlVT # MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVy # YXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpGNzdG # LUUzNTYtNUJBRTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj # ZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKBP7HK51bWHf+FDSh9O # 7YyrQtkNMvdHzHiazvOdI9POGjyJIYrs1WOMmSCp3o/mvsuPnFSP5c0dCeBuUq6u # 6J30M81ZaNOP/abZrTwYrYN+N5nStrOGdCtRBum76hy7Tr3AZDUArLwvhsGlXhLl # DU1wioaxM+BVwCNI7LmTaYKqjm58hEgsYtKIHk59LzOnI4aenbPLBP/VYYjI6a4K # Icun0EZErAukt5PC/mKUaOphUMGYm0PxfpY9BkG5sPfczFyIfA13LLRS4sGhbUrc # M54EvE2FlWBQaJo7frKW7CVjITLEX4E2lxwQG/MuZ+1wDYg9OOErT5h+6zecj67e # enwxeUoaOEbKtiUxaJUYnyQKxCWTkNdWRXTKSmIxx0tbsP5irWjqXvT6t/zeJKw0 # 5NY8hPT56vW20q0DYK2NteOCDD0UD6ZNAFLV87GOkl0eBqXcToFVdeJwwOTE6aA4 # RqYoNr2QUPBIU6JEiUGBs9c4qC5mBHTY46VaR/odaFDLcxQI4OPkn5al/IPsd8/r # aDmMfKik66xcNh2qN4yytYM3uiDenX5qeFdx3pdi43pYAFN/S1/3VRNk+/GRVUUY # WYBjDZSqxslidE8hsxC7K8qLfmNoaQ2aAsu13h1faTMSZIEVxosz1b9yIeXmtM6N # lrjV3etwS7JXYwGhHMdVYEL1AgMBAAGjggE2MIIBMjAdBgNVHQ4EFgQUP5oUvFOH # Lthfd0Wz3hGtnQVGpJ4wHwYDVR0jBBgwFoAUn6cVXQBeYl2D9OXSZacbUzUZ6XIw # XwYDVR0fBFgwVjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9w # cy9jcmwvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3Js # MGwGCCsGAQUFBwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDovL3d3dy5taWNyb3Nv # ZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENB # JTIwMjAxMCgxKS5jcnQwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcD # CDANBgkqhkiG9w0BAQsFAAOCAgEA3wyATZBFEBogrcwHs4zI7qX2y0jbKCI6ZieG # AIR96RiMrjZvWG39YPA/FL2vhGSCtO7ea3iBlwhhTyJEPexLugT4jB4W0rldOLP5 # bEc0zwxs9NtTFS8Ul2zbJ7jz5WxSnhSHsfaVFUp7S6B2a1bjKmWIo/Svd3W1V3mc # IYzhbpLIUVlP3CbTJEE+cC3hX+JggnSYRETyo+mI7Hz/KMWFaRWBUYI4g0BrwiV2 # lYqKyekjNp6rj7b8l6OhbgX/JP0bzNxv6io0Y4iNlIzz/PdIh/E2pj3pXPiQJPRl # EkMksRecE8VnFyqhR4fb/F6c5ywY4+mEpshIAg2YUXswFqqbK9Fv+U8YYclYPvhK # /wRZs+/5auK4FM+QTjywj0C5rmr8MziqmUGgAuwZQYyHRCopnVdlaO/xxSZCfaZR # 7w7B3OBEl8j+Voofs1Kfq9AmmQAWZOjt4DnNk5NnxThPvjQVuOU/y+HTErwqD/wK # RCl0AJ3UPTJ8PPYp+jbEXkKmoFhU4JGer5eaj22nX19pujNZKqqart4yLjNUOkqW # jVk4KHpdYRGcJMVXkKkQAiljUn9cHRwNuPz/Tu7YmfgRXWN4HvCcT2m1QADinOZP # sO5v5j/bExw0WmFrW2CtDEApnClmiAKchFr0xSKE5ET+AyubLapejENr9vt7QXNq # 6aP1XWcwggdxMIIFWaADAgECAhMzAAAAFcXna54Cm0mZAAAAAAAVMA0GCSqGSIb3 # DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G # A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIw # MAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAx # MDAeFw0yMTA5MzAxODIyMjVaFw0zMDA5MzAxODMyMjVaMHwxCzAJBgNVBAYTAlVT # MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1l # LVN0YW1wIFBDQSAyMDEwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA # 5OGmTOe0ciELeaLL1yR5vQ7VgtP97pwHB9KpbE51yMo1V/YBf2xK4OK9uT4XYDP/ # XE/HZveVU3Fa4n5KWv64NmeFRiMMtY0Tz3cywBAY6GB9alKDRLemjkZrBxTzxXb1 # hlDcwUTIcVxRMTegCjhuje3XD9gmU3w5YQJ6xKr9cmmvHaus9ja+NSZk2pg7uhp7 # M62AW36MEBydUv626GIl3GoPz130/o5Tz9bshVZN7928jaTjkY+yOSxRnOlwaQ3K # Ni1wjjHINSi947SHJMPgyY9+tVSP3PoFVZhtaDuaRr3tpK56KTesy+uDRedGbsoy # 1cCGMFxPLOJiss254o2I5JasAUq7vnGpF1tnYN74kpEeHT39IM9zfUGaRnXNxF80 # 3RKJ1v2lIH1+/NmeRd+2ci/bfV+AutuqfjbsNkz2K26oElHovwUDo9Fzpk03dJQc # NIIP8BDyt0cY7afomXw/TNuvXsLz1dhzPUNOwTM5TI4CvEJoLhDqhFFG4tG9ahha # YQFzymeiXtcodgLiMxhy16cg8ML6EgrXY28MyTZki1ugpoMhXV8wdJGUlNi5UPkL # iWHzNgY1GIRH29wb0f2y1BzFa/ZcUlFdEtsluq9QBXpsxREdcu+N+VLEhReTwDwV # 2xo3xwgVGD94q0W29R6HXtqPnhZyacaue7e3PmriLq0CAwEAAaOCAd0wggHZMBIG # CSsGAQQBgjcVAQQFAgMBAAEwIwYJKwYBBAGCNxUCBBYEFCqnUv5kxJq+gpE8RjUp # zxD/LwTuMB0GA1UdDgQWBBSfpxVdAF5iXYP05dJlpxtTNRnpcjBcBgNVHSAEVTBT # MFEGDCsGAQQBgjdMg30BATBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jv # c29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wEwYDVR0lBAwwCgYI # KwYBBQUHAwgwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGG # MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186a # GMQwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3Br # aS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsG # AQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29t # L3BraS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwDQYJKoZIhvcN # AQELBQADggIBAJ1VffwqreEsH2cBMSRb4Z5yS/ypb+pcFLY+TkdkeLEGk5c9MTO1 # OdfCcTY/2mRsfNB1OW27DzHkwo/7bNGhlBgi7ulmZzpTTd2YurYeeNg2LpypglYA # A7AFvonoaeC6Ce5732pvvinLbtg/SHUB2RjebYIM9W0jVOR4U3UkV7ndn/OOPcbz # aN9l9qRWqveVtihVJ9AkvUCgvxm2EhIRXT0n4ECWOKz3+SmJw7wXsFSFQrP8DJ6L # GYnn8AtqgcKBGUIZUnWKNsIdw2FzLixre24/LAl4FOmRsqlb30mjdAy87JGA0j3m # Sj5mO0+7hvoyGtmW9I/2kQH2zsZ0/fZMcm8Qq3UwxTSwethQ/gpY3UA8x1RtnWN0 # SCyxTkctwRQEcb9k+SS+c23Kjgm9swFXSVRk2XPXfx5bRAGOWhmRaw2fpCjcZxko # JLo4S5pu+yFUa2pFEUep8beuyOiJXk+d0tBMdrVXVAmxaQFEfnyhYWxz/gq77EFm # PWn9y8FBSX5+k77L+DvktxW/tM4+pTFRhLy/AsGConsXHRWJjXD+57XQKBqJC482 # 2rpM+Zv/Cuk0+CQ1ZyvgDbjmjJnW4SLq8CdCPSWU5nR0W2rRnj7tfqAxM328y+l7 # vzhwRNGQ8cirOoo6CGJ/2XBjU02N7oJtpQUQwXEGahC0HVUzWLOhcGbyoYICzzCC # AjgCAQEwgfyhgdSkgdEwgc4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n # dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y # YXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNv # MSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpGNzdGLUUzNTYtNUJBRTElMCMGA1UE # AxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIaAxUA # 4G0m0J4eAlljcP/jvOv9/pm/68aggYMwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEG # A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj # cm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFt # cCBQQ0EgMjAxMDANBgkqhkiG9w0BAQUFAAIFAOd+4PQwIhgPMjAyMzAxMjgwMzQ3 # MDBaGA8yMDIzMDEyOTAzNDcwMFowdDA6BgorBgEEAYRZCgQBMSwwKjAKAgUA537g # 9AIBADAHAgEAAgIEvzAHAgEAAgIReDAKAgUA54AydAIBADA2BgorBgEEAYRZCgQC # MSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqG # SIb3DQEBBQUAA4GBABMKTg+WdczHpYTumk3AFzfsVEAmRTVbS+Q10ZagQKqObvg7 # WLiiy8REYknL1algmEK0fWC2b71Vri8ZpqpqCVZ7RatSMz2OJDf33KInE12CJfbk # VKOT9EixDqgpzGgEhfHNlP9uqSw3uP3p7Fwge1+ONoZi1lwdR0n0HS8gpfqjMYIE # DTCCBAkCAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAGq # pTGbC8uyCA4AAQAAAaowDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJAzEN # BgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgsdnBCf+d2fGrXs36+7O0bbVe # Cc7HMvj5lFBMdpaDplIwgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHkMIG9BCBWtQJD # HFq8EeBz3TXugCqRhSI/JCZbATYEIwTG8bMewDCBmDCBgKR+MHwxCzAJBgNVBAYT # AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBU # aW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABqqUxmwvLsggOAAEAAAGqMCIEIFAnZ9+6 # Um+4vhoXdRienw/2NuhUcHojj8w799x2akYBMA0GCSqGSIb3DQEBCwUABIICAGjv # U44XRkwCPdB9XezP7l9k7MMrZ+0LHGrE36GUnr74oAaXEd4meDfqSCctUgsz9M+y # QqTyem62diRJqSm4kqA/lPRGyjZObXgs0Ug185FZ43bgyfImbJ41bR+E+3GGUSCm # WX13JJrTJK5tdOXEZOZf7LcJJ0DRLX0KdwkgsouHODLk84+MyvvhMK5YFgfzuGpX # WEpGRAapzDCRAEalRln50veFyLSSP5Q5l+ZthH3XZ70Ol4cvWFW/Kzhotg+5Tnes # j/fRVWFMWqiWXiVDaHDzqG8FdBojJ8JDNm4FTGD2gDge8qanw8cezBKMFpMioCFs # LDTI4IT74SoaA5auSAF5m8LjjFLI2QZelhS5adwaBA3R0Jv0qpBCGNB7Hb4yUwb1 # ooiuRXqm35rxoKwXEiVOdO9YB5tRGnH3YLMyBXZ+82kqla9MadsOOyXRahasMxA1 # TOu3rqpappTVr9vHMqZ3T8GY/yJLFqvm52tu8QFrwP770jgpuXqcbQiwiw6RQbmf # p05bq5JN3yGWFiJWjWM+1cdqwkGgJfIYXFDhVMaEN/iAhJYfcwB7UH0diZ16B0bl # 7dIiGobYyM9AqcvG9NoVexmpFUKXQLhXmjuKOASYiI79djBOZiCDGQbVDHHg2n6+ # vr98nUrcVGgqvTw5SVnuwOWrJXiVn6nvkQ0bvBIV # SIG # End signature block |