PowerShell Scriptlets to check if NLA is enabled for Remote Desktop

Scenario: You want to see if  NLA (Network Level Authentication) is enabled on all of your servers for Remote Desktop.

The PowerShell code below is not a .ps1, although you can make a .ps1 out of it if you would like.  I like to teach working  “within” PowerShell, not just being a script monkey.

In order to run the code, you will need to open Powershell OR Powershell ISE with an account with elevated permissions to access your servers (Run-AS).  The purpose of working within PowerShell is so that you can  reuse/recycle the code below to do other things too.
Once PowerShell is opened, follow the steps:
  1. Build your $Servers Variable — Select a method to populate $Servers
  2. Run the Query to build the $Results table
  3. Display the $Results — Select a method

 

 

#1. Build your $Servers Variable — Select one of the methods below to populate $Servers

  $Servers = “ExSrv1″,”ExSrv2”   #Feel free to list the servers by name

    #-or-
        $Servers = Import-csv C:tempservers.csv | Select -expandproperty Name   #Create a CSV with a NAME column header

    #-or-
        $Servers =  get-adcomputer -searchbase “OU=Servers,DC=steve,DC=com” -properties Name -Filter *|  Select -ExpandProperty Name  #Pull a list of AD Computers via AD PowerShell

#2. Run the query to build the $Results variable 

$Results = @()
$Servers | %{
    #Collect NLA Data
    $name = $_
    $NLA = Get-WmiObject -class “Win32_TSGeneralSetting” -Namespace rootcimv2terminalservices -ComputerName $name -Filter “TerminalName=’RDP-tcp'” | Select -ExpandProperty UserAuthenticationRequired
   
    #Display in PowerShell Screen
    “$name : NLA_Enabled:$(If($NLA -eq 1){“Yes”}else{“No”})”

    #Add the data to the $results variable
    $ServerObj = New-Object PSObject
    $ServerObj | Add-Member NoteProperty -Name “Server” -value $name
    $ServerObj | Add-Member NoteProperty -Name “NLA_Enabled” -value $(If($NLA -eq 1){“Yes”}else{“No”})
    $Results += $ServerObj
   
    #Reset Variable
    $Name = $null
    $NLA = 0
}

#3. Display the $Results –  Select a method

$Results

    #-or Export the Results –
        $Results | Export-CSV C:tempresults.csv

    #-or Email the Results –
        $Header = @”
        <style>
        TABLE {border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse;}
        TH {border-width: 1px; padding: 3px; border-style: solid; border-color: black; background-color: #6495ED;}
        TD {border-width: 1px; padding: 3px; border-style: solid; border-color: black; text-align: center;}
        tr:nth-child(odd) { background-color:#F2F2F2;}
        tr:nth-child(even) { background-color:white;}
        </style>
“@
        $body =”$($results | ConvertTo-Html -Head $header)”
        $smtp = “smtp.steve.com”
        $to = “steve@steve.com”
        $from = “SteveDoingSomething@steve.com”
        $subject = “Results of NLA”
        send-MailMessage -SmtpServer $smtp -To $to -From $from -Subject $subject -Body $body -BodyAsHtml -Priority high

Collect more than 1000 Results in a Exchange Online Message Trace

Scenario: Recently I was attempting to perform a Message Trace in Exchange Online for a message that went out to 7000+ recipients but realized I could only pull back 1000 results.

Solution:  I used Page and PageSize with the Get-MessageTrace in a loop to pull back more results

 #Collect more than 1000 results in Exchange Online
$P = 1
$messages = $null
do 

    Write-Host “Message Trace – Page $P…” 
    $temp_Messages = Get-MessageTrace -senderaddress maccount@microsoft.com -startdate 8/14/2019 -enddate 8/15/2019 -PageSize 1000 -Page $P
    $P++ 
    $Messages += $temp_Messages 
}until ($temp_Messages -eq $null)

#display messages
$Messages.Count
$Messages

 

 

 

Determine the Management Roles and Commands a user can run in Exchange PowerShell

Scenario –  You want to see what Management Roles and Commands a user can run from Exchange PowerShell

Scriptlet:

#Determine management role assignments for an account
    $1= Get-ManagementRoleAssignment -RoleAssignee <username>
    $1 | Select Role

#Determine what commands are associated with that account
#For a Single Role
Get-ManagementRole Monitoring | FL
    Get-ManagementRole Monitoring | Select -ExpandProperty RoleEntries | Select Name
    Get-ManagementRole Monitoring | Select -ExpandProperty RoleEntries |Sort Name | Select name

#For Multiple Roles from $1
$Roles = @()
    $1.role.name | %{
        $n = $_
        $temp = Get-managementrole $n | Select -ExpandProperty RoleEntries |Sort Name | Select -expandproperty name    

        $temp | %{
            $c = $_
            $ServerObj = New-Object PSObject
            $ServerObj | Add-Member NoteProperty -Name “ManagementRole” -value $n
            $ServerObj | Add-member NoteProperty -Name “Command” -Value $c
            $Roles += $ServerObj
        }

       $n = $null
        $c = $null
    }

#Display $roles
    $roles | Sort Command | Select Command, ManagementRole

 

EWS Script: Perform a RegEx search against all Items in a Mailbox and perform an action

Scenario:  Although RegEx searches are not supported within the Exchange toolset, here is an EWS Script that will perform two kinds of RegEx searches; Patterns AND exact matches (not case sensitive).

The script below is going to do the following:

  • If the mailbox item matches the RegEx, it will move the email item into a folder: BadFolder_Reg
  • If the mailbox item matches the Term, it will move the email item into a folder: BadFolder_Term
  • If any mailbox item has an attachment, it will download it into a directory

Scripts:

#Finding items With RegEx
#Variables
$cred = Get-credential  #credentials will fullaccess to access the mailbox
$mailboxname = “stevetest25@domain.com”  #The Mailbox you wish to perform the query and restore on
$EWS_DLL = “C:Program FilesMicrosoftExchange ServerV15BinMicrosoft.Exchange.WebServices.dll”
$EWS_URL = “https://domain/ews/exchange.asmx&#8221;

#Configure connection to EWS
Import-Module -Name $EWS_DLL
$service = new-object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.Exchangeversion]::exchange2013)
$service.Url = new-object System.Uri($EWS_URL)
$service.UseDefaultCredentials = $false
$service.Credentials = $cred.GetNetworkCredential()

 

#Find all Mailbox folders
$MailboxRootid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName)
$MailboxRoot=[Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$MailboxRootid)
$FolderList = new-object Microsoft.Exchange.WebServices.Data.FolderView(1000)
$FolderList.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep
$findFolderResults = $MailboxRoot.FindFolders($FolderList)

#Bind to BadFolders for RegEx and Terms
$BADfolder_Reg = $findFolderResults | Where displayname -like “BadFolder_Reg”
$BADfolder_Term = $findFolderResults | Where displayname -like “BadFolder_Term”

If($BadFolder_Reg -eq $null){
#Create a Folder called BAD on the Root
“Bad folder doesnt exist, creating it now”
$folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$mailboxname)
$Folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
$NewFolder = new-object Microsoft.Exchange.WebServices.Data.Folder($service)
$NewFolder.DisplayName = “BadFolder_reg”
$NewFolder.Save($Folder.id)

$MailboxRootid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName)
$MailboxRoot=[Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$MailboxRootid)
#Find all folders in the mailbox
$FolderList = new-object Microsoft.Exchange.WebServices.Data.FolderView(1000)
$FolderList.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep
$findFolderResults = $MailboxRoot.FindFolders($FolderList)
$BADfolder_Reg = $findFolderResults | Where displayname -like “BadFolder_Reg”
}

If($BadFolder_Term -eq $null){
#Create a Folder called BAD on the Root
“Bad folder doesnt exist, creating it now”
$folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$mailboxname)
$Folder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
$NewFolder = new-object Microsoft.Exchange.WebServices.Data.Folder($service)
$NewFolder.DisplayName = “BadFolder_Term”
$NewFolder.Save($Folder.id)

$MailboxRootid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName)
$MailboxRoot=[Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$MailboxRootid)
#Find all folders in the mailbox
$FolderList = new-object Microsoft.Exchange.WebServices.Data.FolderView(1000)
$FolderList.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep
$findFolderResults = $MailboxRoot.FindFolders($FolderList)
$BADfolder_Term = $findFolderResults | Where displayname -like “BadFolder_Term”
}

#Create Variables for Search

$ItemPropset = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
$i = 0
$i_end = $findfolderResults.item.count
$reg = @()

$reg +=  “[1-9][0-9]{2}-[0-9]{2}-[0-9]{4}^d”

$reg += “(^|D)(d{3}-d{2}-d{4})(D|$)”

$DownloadDirectory = “\servershare$attachments”
$term = ” test123 “,” steve “,” batman “,” superman ”

#Loop each mail folder and perform the search
Do{
If(($findFolderResults.Folders[$i]).DisplayName -notlike “Badfolder*”){

“Checking Folder: $(($findFolderResults.Folders[$i]).DisplayName)”
$ItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000)

Do{
$AqsString = “System.Message.DateReceived:01/01/2000..12/31/2099”
$fiItems = $findFolderResults.Folders[$i].FindItems($AqsString,$ItemView)
$ItemView.offset += $fiItems.Items.Count
[Void]$service.LoadPropertiesForItems($fiItems , $ItemPropset)

foreach($Item in $fiItems.Items){
“Checking on $($Item.Subject)”
#Check for attachments#########################
If($item.Hasattachments -eq $true){
“Attachment Detected on $($Item.Subject)”
foreach($attach in $Item.Attachments){
$attach.Load()
$fiFile = new-object System.IO.FileStream(($downloadDirectory + “” + $attach.Name.ToString()), [System.IO.FileMode]::Create)
$fiFile.Write($attach.Content, 0, $attach.Content.Length)
$fiFile.Close()
write-host “Downloaded Attachment : ” + (($downloadDirectory + “” + $attach.Name.ToString()))
}
}
#^Check for attachments#########################

#Check for Reg#########################
$reg_result = $false
$b_temp = $Item.body.text
#Loop regex
$reg | %{
$r = $b_temp -match “$_”
“Result: $r”
if($r -eq $true){“Setting $reg_result to $r”;$reg_result = $true}
}

#display
“$Reg_result – The MSG with Subject: $($Item.subject) ”

If($reg_result -eq $true){
“Moving $($Item.Subject) to BadFolder_reg”
[VOID]$Item.Move($BadFolder_reg.Id)}
#^Check for Reg##################################################

#Check for Terms#########################
$Term_result = $false
$b_temp = $Item.body.text
#Loop term
$term | %{

$rr = $b_temp -match $_
“Result: $rr”
if($rr -eq $true){“Setting $term_result to $rr”;$term_result = $true}
$term_temp = $null
}

#display
“$term_result – The MSG with Subject: $($Item.subject) ”

If($term_result -eq $true){
“Moving $($Item.Subject) to BadFolder_term”
[VOID]$Item.Move($BadFolder_term.Id)}
#^Check for Terms##################################################

#clean var
$r = $null
$b_temp = $null

}
}While($fiItems.moreavailable -eq $true)
}

$i++
“FolderID Counter $i”

}While ($i -le $i_end)