City et Timezone mapping en PowerShell

Bonjour à tous, ca fait longtemps que je vous ai pas partager un petit article sur PowerShell, non ? Du coup aujourd’hui on parle de City et Timezone mapping en PowerShell. En effet, j’ai eu besoin de faire un mapping entre des villes et pays que j’avais en entrée dans un AD et la timezone associé. Pour que le support puisse appeler les utilisateurs sur les bons créneaux. Et… c’était pas direct que ca en a l’air.

Alors je vais couper cours, pas de budget à y mettre. Donc les truc tout fait via API (comme Google Map platform), c’est pas possible. Pareil, pas de coordonnée que des noms villes et pays. Donc les trucs à base coordonnées GPS pas ouf non plus. Enfin les trucs gratuit comme timezonedb, c’était jouable. Mais j’avais 80 000 objets à traiter, avec la limitation a 1 call par seconde j’en aurait eu pour 22h minimum.

Bref, au final , je me suis rabatu sur geonames.org. Les données sont en accès libre Download / Webservice et j’ai fait un croisement « en local » (bien à l’ancienne comme il faut) que je vous donne ci-dessous.

#Download geonames database https://download.geonames.org/export/dump/
$datafile = "cities500"
Invoke-WebRequest -Uri ("https://download.geonames.org/export/dump/"+$datafile+".zip") -OutFile "$datafile.zip"
Expand-Archive ("$datafile"+".zip") -Force
Remove-Item ("$datafile"+".zip")

#ajout de l'header manquant dans les fichiers sources
$header = "'geonameid'`t'name'`t'asciiname'`t'alternatenames'`t'latitude'`t'longitude'`t'feature class'`t'feature code'`t'country code'`t'cc2'`t'admin1 code'`t'admin2 code'`t'admin3 code'`t'admin4 code'`t'population'`t'elevation'`t'dem'`t'timezone'`t'modification date'"
@($header) + (Get-Content "$datafile\$datafile.txt") | Set-Content "$datafile\$datafile.txt"
#Chargement en mémoire de la base
$cityinformation = Import-Csv "$datafile\$datafile.txt" -Delimiter "`t"

# récupération des comptes
$domains = @("my.domain.tld")
$domainscsv = @("my.domain.tld.csv")

foreach ($d in $domains){
	$result = @()
	$domaindata = Get-ADUser -filter * -properties @('PwdLastSet','distinguishedName','company','co', 'c', "l" ,'mail') -Server $d | sort PwdLastSet | Select Name,mail,distinguishedName,company,co,c,l,@{Name='PwdLastSet';Expression={[DateTime]::FromFileTime($_.PwdLastSet)}}
	$i=0
	$percent=0
	# pour chaque compte récupéré
	foreach ($user in $domaindata){	
		if($user.l -ne "" -and $null -ne $user.l){
			Write-Progress -Activity "TZ Search in Progress" -Status "$i / $($domaindata.count) Complete:" -PercentComplete $percent
			#croiser les informations de city et country avec les attributs de l'utilisateur
			$TZ = ($cityinformation | Where-ObjectFast {($_.'''name''' -eq $user.l) -and ($_.'''country code''' -eq $user.c)}).'''timezone'''
		}
		# construction du résultat 
		$user | Add-Member -Name timezone -MemberType NoteProperty -Value "$TZ"
    $result += $user
		$i++
		$percent=($i/$domaindata.count)*100
	}
	# Export dans le fichier
	$result | Export-Csv -Path "$d.csv" -Force
}

$domainscsv | Compress-Archive -DestinationPath "userlastpasswordreset.zip"

Send-MailMessage -From 'etienne@geekeries.org' -To 'support@geekeries.org' -Subject 'Password last reset date' -Body "Hello, Please see attachments for each domain of the last password update. Regards" -Attachments "userlastpasswordreset.zip" -Priority High -SmtpServer 'smtp.geekeries.org'

Remove-Item (@($domainscsv)+@("userlastpasswordreset.zip"))
Remove-Item ".\$datafile" -Recurse

Ceux qui ont jeté un œil au script auront remarquer le Where-ObjectFast que j’ai trouvé sur powershell.one. J’ai trouver l’article super intéressant. Il aide pour comprendre comment ca fonctionne sous le capot. Cela a permis d’optimiser un peu les performances du script. Qui, il faut le dire, ne sont pas fofolles sur 80000 objets.

Dans les autre optimisations, notez que geonames proposes des DB avec villes plus ou moins grandes. Pour les tests privilégiez les données des grandes villes (DB plus petites), ce qui accélère grandement le script

Bref, ca faisait un bon bout de temps que j’avais pas écrit de PowerShell. Ca m’a dérouillé un peu et ça fait du bien de faire ce script de City et Timezone mapping. You’ll find peace in code, hein ! Voilà, c’est tout pour l’instant, toujours 2 tonnes d’articles et notes dans les drafts à vous partager… Et pas 2s d’affilée pour les écrire donc gardez un œil sur le blog, ça finira par sortir, à je ne sais pas quel rythme… Et en attendant Geekez bien !

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.