Posted in Computers and Internet

Exchange: How to list memberOf groups of a distribution group?


When I wrote a script to migrate distribution groups to Office 365 from On-Prem Exchange server, I had a requirement to list the parent (memberOf) groups. So I can migrate them in order or do not lose the group memberships during migration.

So how do we list the parent groups of a DL? There are different methods to get the memberOf groups for on-premises or Office 365 environment.

On-Premises

I am using AD cmdlets, because they are very easy use. This command will display the parent (memberof) groups of their Email:

Get-ADGroup <Group Name> -Properties memberOf | Select-Object memberOf | Where-Object { $dn =[string] $_.memberOf ; Get-ADObject $dn -Properties mail | Select-Object mail}

Office 365/Exchange Online

I end up using Exchange Online cmdlets in Exchange online. It may be little slower then On-Prem command. Idea is run Get-Group command with a filter if the group show up in any group’s members. This will list the memberOf groups (of them email address).

$GroupDN = (Get-Group ).distinguishedName
$filter = "Members -eq '$GroupDN'"
(Get-Group -Filter $filter).WindowsEmailAddress

Posted in Computers and Internet

Office 365: How to correct UserPrincipalName for On-premises AD sync’ed account?


Say you end up with a wrong UserPrincipalName for an MSOL account which is sync’ed from On-Prem Active Directory like this: username@company.onmicrosoft.com, Which is obviously wrong UPN. The correct UPN supposed to be like username@company.com and it should match the user’s PrimarySMTPAddress.

I am sure you tried to correct it in Office 365 Admin Center, where UPN is grayed out. You may have tried MSOL PowerShell command Set-MSOLUser which does not have the parameter -UserPrincipalName. Right? That why you are here.

Solution: Easy Peacy. You have to use the another MSOL PowerShell command like this:

Set-MsolUserPrincipalName
-UserPrincipalName username4892@company.onmicrosoft.com -NewUserPrincipalName username@company.com 

That’s it. You have done it. Have an coffee! You deserve it! 🙂

Posted in Computers and Internet

Active Directory: Send password expiry Email notice to users


Here is very useful script written by me. Feel free to use on your network.

This script queries the local Active Directory for users whose password is expiring in given number of days, then send email notice to the user.

Download the PowerShell Script

The source code:

 <#
    **************************************************************************************************
    ** Script: Email-PasswordExpiry-Notice.ps1                                                      **
    ** Purpose: Send Email Notice to users before their AD passwrod expires                         **
    ** Note: Make sure to provide your own values with the comment "$# <--- "" in this script       **
    **                                                                                              **
    ** Written by: Anand, the Awesome, Venkatachalapathy                                            **
    **************************************************************************************************
#>

$DaysBeforeExpiry = 5 # <--- Change your own number of days before password expiry (to start SPAMing users)

# Query AD for users whose password is expiring close to $DaysBeforeExpiry days
$users = Get-ADUser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} –Properties "DisplayName", "msDS-UserPasswordExpiryTimeComputed","mail"  `
| Where-Object {$_.mail -ne $null } `
| Select-Object -Property "Displayname",@{Name="ExpiryDate";Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}},"Mail","SamAccountName" `
| Where-Object {$_.ExpiryDate -lt (Get-Date).AddDays($DaysBeforeExpiry) -and $_.ExpiryDate -gt (Get-Date) } 


#Send Email to the users from the above query results
$from = "IT-Town-Crier@company.com"  # <--- Change your own From Email address
$smtpserver = "smtp.compnay.com"     # <--- Type your local SMTP server

foreach($user in $users)
{
    $expirydays = (([DateTime]$user.ExpiryDate) - (get-date)).Days
    $to = $user.mail
    $username = $user.SamAccountName
    $domainname = env:USERDOMAIN
    $subject = "Your Password Will Expire in $expirydays Days"

    $body = @"
Your Active Directory account ($domainname\$username) Password Will Expire in $expirydays Days. 

Change your password when possible. On Windows computer, press Control-Alt-Delete & choose change password. 

--Your Friendly Neighbourhood IT 
"@
    
    $to
    $subject
    $body
    '*' * 80
    Send-MailMessage -Body $body -From $from -SmtpServer $smtpserver -Priority High -Subject $subject -To $to 

}

<#
    ***************** The End of the Script *****************
#> 
Posted in Computers and Internet

Active Directory – PowerShell – Cannot search by null value attributes


If you tried to filter results with any AD cmdlets in PowerShell, you quickly finds out it is not possible with “-Filter” option. For example, I tried to list any user with no Mail attribute value is null:

PS E:> Get-ADUser -Filter { mail -ne $null }
 Get-ADUser : Variable: 'null' found in expression: $null is not defined.
 At line:1 char:1
+ Get-ADUser -Filter { mail -ne $null }
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
       + CategoryInfo : InvalidArgument: (:) [Get-ADUser], ArgumentException
       + FullyQualifiedErrorId : ActiveDirectoryCmdlet:System.ArgumentException,Microsoft.ActiveDirectory.Management.Commands.GetADUser 

Well, the solution is to use -LDAPFilter instead of -Filter option. Here is the working command:

PS E:> Get-ADUser -LDAPFilter '(!mail=*)' -ResultSetSize 5 -Properties mail | Select-Object Name,Mail
 Name          Mail
 ----          ----
 Josh Doe         
 uvkaseya            
 sg-mcafee          
 Guest             
 IUSR_WEB-SR04     

So the trick is ‘(mail=*)’ filter brings all user accounts with mail account has any value. Adding [NOT] operator in front of mail ‘(!mail=*)’ in the LDAPFilter results with all user accounts with mail attribute is empty.

So use the filter string with any AD property to search like this: -LDAPFilter ‘(!mail=*)’

Posted in Computers and Internet

Active Directory: Password Expiry date Report for all accounts


I had a requirement to generate password expiry date report for all accounts to validate a password policy change. Here is what I came up with (who know someone have same need for this report).

Important point is the calculated property msDS-UserPasswordExpiryTimeComputed. Which is in Long Date format.

It will create an CSV file on the same directory on where the script runs.

Get-ADUser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False}  –Properties "DisplayName", "msDS-UserPasswordExpiryTimeComputed"
 | Select-Object -Property "Displayname",@{Name="ExpiryDate";Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}} `
 | Export-Csv -path .\Password-Expiry-Report.csv -NoTypeInformation

Here is the same report:

“Displayname”,”ExpiryDate”
“Tim Dangthatsme”,”8/23/2019 9:23:10 AM”
“Don Anonymous”,”7/31/2014 3:17:20 AM”
“Robert Dome”,”12/17/2019 8:14:17 AM”
“Introvert Hopkins”,”9/6/2019 10:57:07 AM”

Posted in Computers and Internet

Fun: Get Weather information in PowerShell


Found these helpful sites (http://ipinfo.io and http://wttr.in and wrote an script to get and display weather information of your current location. Now in a shell, I can check weather information too. 🙂

<#
 Script: Get-Weather.ps1
 Description: This script will
     * Get current location
     * Find the Weather info
     * Display the weather info

 Fun fact: This command will display the GPS location
 information

 Invoke-RestMethod -URI "ipinfo.io" -Method GET | Select  City,Region,Country,loc | FT -auto

#>

#Get current location (city)
$City = (Invoke-RestMethod -URI "ipinfo.io" -Method GET).City

#get Weather info
$weather = Invoke-WebRequest -Uri "http://wttr.in/$City"
$WeatherInfo = $weather.ParsedHtml.body.outerText

#Display the weather info
$WeatherInfo

Posted in Computers and Internet

PowerShell: Create a unique log file name out of date/time


I create log files or transcripts all the time with my PowerShell scripts. I needed a reliable filename with date and time. So I wrote an quick function to format the date and time that easy to read and identify the list of files.

Here it is. Use the function for your purposes. The code includes an example code on how I use the function.

<#
 Function to return current date and time formatted to use log file
 name. 
 How it works: Call the function and use the returned value to 
 create an log file name in your code. 
 E.g., 
 $logfilename = "My-Script-" + (date_time()) + ".log"
 #>
 function date_time()
 {
     return (Get-Date -UFormat "%Y-%m-%d_%I-%M-%S_%p").tostring()
 }


# Example use of function
# Create an log file name and assign to $logfilename variable
 $logfilename = "My-Script-" + (date_time) + ".log"
 
# Display the log file name
 $logfilename

Example file name created by this script:

My-Script-2019-06-12_08-26-30_PM.log

Posted in Computers and Internet

How to unblock an ActiveSync Mobile device in Exchange Online?


If the user’s ActiveSync device is blocked (Quarantined), User might be getting this email:

Subject: Your device is temporarily blocked from synchronizing using Exchange ActiveSync until your administrator grants it access.

Your device is temporarily blocked from accessing content via Exchange ActiveSync because the device has been quarantined. You don’t need to take any action. Content will automatically be downloaded as soon as access is granted by your administrator.

There are 3 ways to unblock the mobile device in Exchange On-Prem and Exchange Online. I will show you here all 3 ways. I personally use PowerShell. So, the PowerShell way first.

Unblock the ActiveSync Device using PowerShell

  1. Open PowerShell and connect to Exchange server Or Exchange Online
  2. Run Get-CASMailbox command and NOTE Down the “blocked ActiveSync device id”. E.g., See Below. Notice the blocked device id: androidc274977591
PS E:\> Get-CASMailbox -Identity anandTheAwersome | Select-Object "*ActiveSync*"
ActiveSyncAllowedDeviceIDs         : {4E6F74657361613733653433336533}
ActiveSyncBlockedDeviceIDs         : {androidc274977591}
ActiveSyncMailboxPolicy            : Default
ActiveSyncMailboxPolicyIsDefaulted : True
ActiveSyncDebugLogging             : False
ActiveSyncEnabled                  : True
HasActiveSyncDevicePartnership     : True
ActiveSyncSuppressReadReceipt      : False

3. Add the noted blocked device id into Allowed Devices in CAS Mailbox Properties.

Set-CASMailbox -Identity anandTheAwersome -ActiveSyncAllowedDeviceIDs @{Add='androidc274977591'}

4. To verify, Run the Get-CASMailbox again to see the device id is in ActiveSyncAllowedDeviceIds list.

PS E:\> Get-CASMailbox -Identity anandTheAwersome | Select-Object "*ActiveSync*"
ActiveSyncAllowedDeviceIDs         : {4E6F74657361613733653433336533,androidc274977591}
ActiveSyncBlockedDeviceIDs         : {}
ActiveSyncMailboxPolicy            : Default
ActiveSyncMailboxPolicyIsDefaulted : True
ActiveSyncDebugLogging             : False
ActiveSyncEnabled                  : True
HasActiveSyncDevicePartnership     : True
ActiveSyncSuppressReadReceipt      : False

That’s It. Give it a minute or two. The Mail/Calendar client App in the device will start synchronizing. Now, for the underlings who gets scared of PowerShell, I will show how to do this in Exchange Admin Console.

(Way 1) Unblock the Active Sync Device in “Mobile Device Details”

  1. Open ECP console in your favorite browser
  2. Go to Mailboxes and find and select the user’s mailbox.
  3. On the right-side pane, click on “View Details” under “Mobile Devices
  4. Select the blocked device (Status says “Access Denied”). Click on the Second Icon to “Allow” the device.
  1. Click “Save” button.

(Way 2) Unblock the Active Sync Device in “Mobile Device Details”

  1. In Exchange Console Panel, Select Mobile
  2. In “Mobile device access” tab, find the user and blocked device in “Quarantined Devices
  3. After you find and select the device, click on the second button to “Allow” the device
  1. Give it a minute or two, client app will start synchronizing.

Hope that was easy. If you like this blog, leave me a “holla”.

Posted in Computers and Internet

Solution: Invoke-WebRequest : The request was aborted: Could not create SSL/TLS secure channel.


You are running Invoke-WebRequest and hit with “Could not create SSL/TLS secure channel”, It simply means TLS 1. 2 is not being used.

Windows selects most strong cryptography from the list. How do you know what’s your crypto list?

Display the list of cryptos form this .Net Class variable:

PS E:> [Net.ServicePointManager]::SecurityProtocol
Tls, Tls11, Tls12

My computer shows three cryptos and most strong one is TLS 1.2. If you get the above error message ( “Could not create SSL/TLS secure channel” ), that means the most strong crypto is not supported by the web site you are accessing. (Is Tls12 missing?)

Since this is PowerShell, you can fix it two ways. For temporarily enable TLS 1.2 and make a Invoke-WebRequest,

Run this command before you run Invoke-WebRequest cmdlet. Young only need to set the security protocol to TLS 1.2 only once in the script.

[Net.ServicePointManager]::SecurityProtocol =[Net.SecurityProtocolType]::Tls12

Obviously when you finish running the script, security protocol assignment is lost. It goes back to computer’s default setting.

If you need to make it permanent, you could add TLS 1.2 in the cryptography list in Registry. Open PowerShell in Administrative mode (Run as Admin), then add these registry entries:

Set strong cryptography on 64 bit .Net Framework (version 4 and above)

Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord 

Set strong cryptography on 32 bit .Net Framework (version 4 and above)

Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord  

You have close all PowerShell Windows and reopen it to take effect the registry settings.

Did that help? leave me a reply.