Thursday, May 19, 2022

Intune Autopilot set initial timezone for users with Powershell

I had a request to automatically set the timezone for users on autopilot provisioned devices. There are other ways to solve this that others have published, but I wasn't keen on relying on location services on the endpoint or calls out to maps APIs. I thought about hitting a public internet API to get location that way, but if you're backhauling internet at all that could be inaccurate. So posting my solution here since I did it a bit differently - maybe more simple, maybe not - but it did work for me. I used AD groups - one for each time zone, with each group having dynamic membership based on 'user.city = xyz' or 'user.city=abc' Then I deployed a per-user script that grabs the local UPN, queries AD via Graph API to find which timezone group they're in, and sets accordingly. Code is not super clean, but gets the job done for now.


#Script created May 2022 - this checks a user's group membership against dynamic Azure AD groups via Graph
#That group membership then sets the local timezone, or is ignored if they're in the 'NoTimezone' group
#The Azure AD groups are dynamic groups, which key off the 'city' attribute of users
#Example: 'Intune-Timezone-Pacific' dynamic group would have membership rules like so:
#(user.city -eq "Seattle") or (user.city -eq "Portland") or (user.city -eq "San Francisco")
#logs data to %temp% for validation


#Simple logging function
$Logfile = "$env:temp\settz_$env:computername.log"
function WriteLog {
    Param ([string]$LogString)
    $Stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss")
    $LogMessage = "$Stamp $LogString"
    Add-content $LogFile -value $LogMessage
}

#Install or import Graph Module
If (Get-Module -ListAvailable -Name "Microsoft.Graph") {
    WriteLog "Module is already installed"
}
Else { 
    Install-module "Microsoft.Graph -Scope CurrentUser" 
}

if ((Get-Module -Name "Microsoft.Graph.Users")) {
    WriteLog "Users Module is already imported"
}
else {
    import-module "Microsoft.Graph.Users"
}

if ((Get-Module -Name "Microsoft.Graph.Authentication")) {
    WriteLog "Auth Module is already imported"
}
else {
    import-module "Microsoft.Graph.Authentication"
}

WriteLog $error

## Connect Graph API ##
# Populate with the App Registration details and Tenant ID
$appid = 'yourappid'
$tenantid = 'yourtenantid'
$secret = 'yoursecret'
 
$body = @{
    Grant_Type    = "client_credentials"
    Scope         = "https://graph.microsoft.com/.default"
    Client_Id     = $appid
    Client_Secret = $secret
}
 
$connection = Invoke-RestMethod `
    -Uri https://login.microsoftonline.com/$tenantid/oauth2/v2.0/token `
    -Method POST `
    -Body $body
 
$token = $connection.access_token

# Authenticate Graph
Connect-MgGraph -AccessToken $token

#grab current user upn
$upn = whoami /upn
$string = "Checking local user $upn on $env:computername "
WriteLog $string
$string = "Current tz on host is $(get-timezone) "
WriteLog $string

#list groups via graph api query
$groups = (Get-MgUserMemberOf -UserId $upn).additionalproperties.displayName
WriteLog $groups

#check if user is member of NoTimezone group to override logic
$notz = (Get-MgUserMemberOf -UserId $upn).additionalproperties.displayName -match 'Intune-Timezone-NoTime*'
If ($notz -eq "Intune-Timezone-NoTimezone") {
    $tz = $notz
    WriteLog "Overriding due to NoTimezone group membership and not setting local tz"
}
else {
    #grab first group listed that matches naming convention for timezone groups
    $tz = (Get-MgUserMemberOf -UserId $upn).additionalproperties.displayName -match 'Intune-Timezone*' | Select-Object -first 1
    $string = "TimeZone group found is $tz "
    WriteLog $string
}

#Just for reference Group Names/Ids
#Intune-Timezone-Pacific = "Yourgroupid"
#Intune-Timezone-Mountain = "Yourgroupid"
#Intune-Timezone-Central = "Yourgroupid"
#Intune-Timezone-Eastern = "Yourgroupid"
#Intune-Timezone-NoTimezone = "Yourgroupid"

#Set PC timezone based on results from graph api query
switch ($tz) {
    "Intune-Timezone-Pacific" { Set-TimeZone -Id "Pacific Standard Time" }
    "Intune-Timezone-Mountain" { Set-TimeZone -Id "Mountain Standard Time" }
    "Intune-Timezone-Central" { Set-TimeZone -Id "Central Standard Time" }
    "Intune-Timezone-Eastern" { Set-TimeZone -Id "Eastern Standard Time" }
    "Intune-Timezone-NoTimezone" {}
}

$string = "After script run tz on host is $(get-timezone) "
WriteLog $string
WriteLog "Errors:"
WriteLog $error

# Disconnect Graph
Disconnect-MgGraph