Migration des Profils CITRIX UPM vers FSLOGIX en « oneshot »

Petit partage de mon script powershell qui permet de migrer les profils Citrix UPM vers un conteneur FSLOGIX

Vous souhaitez migrer un « oneshot » vos profils Citrix gérés par UPM vers des profils Citrix géré par FSLOGIX ? Alors ce script est pour vous !

Le script :


#Check le repository des profils Citrix D:\Profils et pour chaque sous répertoire (exemple : D:\Profils\toto) lance la migration
Get-ChildItem -path  D:\Profils |  Where-Object { $_.PSIsContainer } |

ForEach-Object {
#A modifier en fonction des sous répertoires contenant le profil Citrix :
$path = $_.FullName + "\Win2016v6\UPM_Profile"
$sam = $_.Name
$vhdfolder = $_.FullName

#A modifier pour renommer le VHD. Je place le VHD dans le même répertoire parent du profil Utilisateur (exemple : D:\Profils\toto\Profile_toto-Citrix2016.vhdx) :
$vhd = Join-Path $vhdfolder ("Profile_"+$sam+"-Citrix2016"+".vhdx")

#Rapport en cas d'erreur
$file = "D:\Profils\1_rapport.html"

Write-host $_.Name -ForegroundColor Green
Write-Host $path -ForegroundColor Green

#Test si un VHD est déjà présent. Si non, création du VHD + montage. Si oui, montage en T: du VHD. Le check permet de faire une full en journée et le delta la nuit (plus rapide)
if (!(test-path $vhd)) {
@"
create vdisk file=$vhd maximum 8192 type=expandable

sel vdisk file $vhd

attach vdisk

create part prim

select part 1

format fs=ntfs quick

sel vdisk file=$vhd

sel part 1

assign letter=T

"@ | diskpart

Start-Sleep -s 2
#creation répertoire "Profile" dans VHD
New-Item -Path T:\Profile -ItemType directory | Out-Null
start-process icacls "T:\Profile /setowner SYSTEM"
Start-Process icacls -ArgumentList "T:\Profile /inheritance:r"
Start-Process icacls -ArgumentList "T:\Profile /grant SYSTEM`:`(OI`)`(CI`)F"
Start-Process icacls -ArgumentList "T:\Profile /grant Administrateurs`:`(OI`)`(CI`)F"
Start-Process icacls -ArgumentList "T:\Profile /grant $env:userdomain\$sam`:`(OI`)`(CI`)F"

}
else {

@"
sel vdisk file=$vhd

attach vdisk

sel part 1

assign letter=T

"@ | diskpart

}

#Migration du contenu de l'UPM vers le VHD
"Copie de $path vers T:"
$process = (Start-Process -FilePath robocopy -ArgumentList "$path T:\Profile /E /Purge /r:0" -PassThru -Wait)
Write-Output "Processus Robocopy termine avec le code suivant : "$process.ExitCode
if ($process.ExitCode -eq "1" -Or $process.ExitCode -eq "3") {
			Write-host "==Données de $sam Transférées==" -ForegroundColor Green
		}else {
			Add-Content -Path $file -Value @"
Erreur lors de la copie des données de $sam

"@
		}

#Démontage du disk vhd
@"
sel vdisk file=$vhd

detach vdisk
"@ | diskpart


Write-host "===============================" -ForegroundColor Yellow
Write-host "Fin de la création pour $sam" -ForegroundColor Yellow
Write-host "===============================" -ForegroundColor Yellow
Start-Sleep -s 3
}

Explication rapide :

Exemple avec l’utilisateur « toto » :

Le repository du profil Citrix se trouve dans : D:\Profils\toto
Dans son dossier « toto » il y a un sous dossier nommé « Win2016v6 »

Donc : D:\Profils\toto\Win2016v6 correspond à son profil Citrix géré par UPM. Son profil « WINDOWS » est présent à l’intérieur, dans le dossier « UPM_Profile ». Donc le chemin complet de son profil windows est : D:\Profils\toto\Win2016v6\UPM_Profile
Le but étant de copier le contenu du « UPM_Profile » et de le coller dans un conteneur FSLOGIX, le vhdx.
Le conteneur FSLOGIX, via le script, sera créé dans le répertoire : D:\Profils\toto

Quelques points rapides :

  • La migration ne supprime rien du profil UPM (simple copie) donc un retour en arrière est possible.
  • Pensez à modifier les variables : $path $vhdfolder et $vhd si vous souhaitez déplacer le vhd autre part que dans le répertoire parent de l’utilisateur.
  • Laissez bien les « sleep » ainsi que les espaces dans le block script de diskpart.
  • Un fichier de log (basic) est créé et alimenté à chaque fois que robocopy renvoi un code « exit » différent de 1 ou 3. A perfectionner.

Lister et Désactiver les Comptes Citrix Gateway (NetScaler Unified Gateway)

Hey ! Ça fait longtemps que j’avais pas publié un article sur mon site !
Changement de vie personnelle fut radi ….. « On s’en fout !!! On veut ton script !!!!! »

Aujourd’hui je vous propose un script permettant de lister les Utilisateurs AD ayant un accès NetScaler Unified Gateway et de les désactiver en un clic !

Cas pratique :
Un utilisateur ne doit plus faire de « télé travail » (pour X raisons) et dispose d’un téléphone personnel sur lequel il avait un accès distant à Citrix (Via authentification à double facteur ‘Google Authenticator’).
Vous ne pouvez pas désactiver le compte AD car cela signifie qu’une fois au bureau il ne pourra plus se connecter. Vous devez donc lui supprimer l’ « Enrollement » de son téléphone.

L’enrollement du téléphone se situe dans un attribue AD : « UserPreference » et est délimiter par un @# au début et une « , » à la fin :

ATTENTION : Cet attribut ne contient pas que cela. Il peut arriver qu’il y ait d’autres paramètres de renseignés.

La requête Powershell :

Get-ADUser -LDAPFilter "(userParameters=*#@*,*)" | Select Name,SamAccountNam

« Oui mais Xavier, tu avais parler de lister et désactiver en un clic !!!! »

Effectivement, j’ai créé une application pour que nos personnes de l’exploitation/support puissent désactiver les accès Unified Gateway sans à avoir à modifier les attributs directement dans l’AD.
Ce que je vous propose c’est ceci :

Pour le moment :
– Un Bouton pour désactiver + confirmation avant désactivation
– Un Bouton pour Quitter

Attention, vous ne pouvez sélectionner qu’un User à la fois

Le code de l’application :

#Modules
[reflection.assembly]::LoadWithPartialName( "System.Windows.Forms")
ipmo activedirectory
$image = [system.drawing.image]::FromFile("D:\script\citrix_netscaler.jpg")

function liste {
#Paramètre de la fenêtre
$Form = New-Object System.Windows.Forms.Form
$Form.AutoSize = $True
$Form.text = "Selection de l'accès distant à désactiver"
$Form.MaximizeBox = $false

#Header avec Image (pour faire genre c'est beau)
$Header = new-object Windows.Forms.PictureBox
$Header.width=200
$Header.height=80
$Header.top=10
$Header.left=10
$Header.Image=$image
$header.SizeMode = 'StretchImage'
$form.Controls.Add($Header)

#Creation de la liste à cocher
$ListeCTX=New-Object System.Windows.Forms.CheckedListBox
$ListeCTX.Location = '10,100'
$ListeCTX.Size = '250,300'
$form.Controls.Add($ListeCTX)
$ctx = Get-ADUser -LDAPFilter "(userParameters=*#@*,*)" | Select Name,SamAccountName
$ListeCTX.DataSource = [collections.arraylist]$ctx
$ListeCTX.DisplayMember = 'SamAccountName'
$ListeCTX.CheckOnClick = $true

# Bouton désactiver l'accès distant
$BoutonDisable= new-object System.Windows.Forms.Button
$BoutonDisable.Location = '280, 100'
$BoutonDisable.Size = '150,50'
$BoutonDisable.Text = 'Désactiver'
$BoutonDisable.add_click({
$ListeCTX.CheckedItems | select SamAccountName
$Users =[array]$($ListeCTX.CheckedItems).SamAccountName
$reponse = confirmation "Voulez vous vraiment désactiver l'accès distant de $Users ?" "Confirmer"
if ($Reponse -eq [System.Windows.Forms.DialogResult]::Yes)
{
Write-Host "désactivation de l'accès distant de $Users"
$User = $Users
Write-Host $User -ForegroundColor Red
$KeyNOW = Get-ADUser -Filter "sAMAccountName -eq '$User'" -Properties * | Select-Object -ExpandProperty userParameters
$KeyNEW = $KeyNOW -replace '(?<=#@)(.*)(,)'
Write-Host $KeyNOW -ForegroundColor Yellow
Write-Host $KeyNEW -ForegroundColor Green
Set-ADUser -Identity "$User" –replace @{userParameters=$KeyNEW} -Verbose | OK "L'utilisateur $User n'a plus d'accès à distance" "Opération réussie"
}
else
{
Write-Host "annulation"
}
})
$form.Controls.Add($BoutonDisable)

#CopyRight
$CopyRight = New-Object Windows.Forms.Label
$CopyRight.Location = New-Object Drawing.Point 370,410
$CopyRight.Size = New-Object Drawing.Point 110,15
$CopyRight.text = "Copyright XBI. Version 2"
$CopyRight.Font = New-Object System.Drawing.Font("Microsoft Sans Serif", 7)
$form.Controls.Add($CopyRight)

#Bouton Quitter
$BoutonQuitter= new-object System.Windows.Forms.Button
$BoutonQuitter.Location = '50, 410'
$BoutonQuitter.AutoSize = $True
$BoutonQuitter.Text = 'Quitter'
$BoutonQuitter.add_click({
$form.Close()
})
$form.Controls.Add($BoutonQuitter)

[void]$Form.ShowDialog()
}

function confirmation { 
$message_Out = $args[0]
$titre= $args[1]
$Btn = 4  
$Icon = 48
Return [System.Windows.Forms.MessageBox]::Show($Message_Out, $Titre , $Btn, $Icon)
} #Generation fenetre de confirmation

function OK { 
$message_Out = $args[0]
$titre= $args[1]
$Btn = 0  
$Icon = 48
[System.Windows.Forms.MessageBox]::Show($Message_Out, $Titre , $Btn, $Icon)
} #Generation fenetre OK

liste

A modifier :
- La variable $image (afin d'avoir une jolie image en haut à gauche) Peu importe la taille de l'image : $header.sizemode est là pour "fit" l'image dans le "header".

La partie la plus intéressante du script est celle ci :

$KeyNOW = Get-ADUser -Filter "sAMAccountName -eq '$User'" -Properties * | Select-Object -ExpandProperty userParameters 
$KeyNEW = $KeyNOW -replace '(?<=#@)(.*)(,)'
Write-Host $KeyNOW -ForegroundColor Yellow
Write-Host $KeyNEW -ForegroundColor Green

La variable $keyNOW correspond à la chaîne de caractère située dans l’attribut "userParameters"
Cette valeur est ensuite éditée via un RegHEx (merci au site :
https://regexr.com/ ) pour y extraire la valeur située entre le #@ et la virgule (donc le paramétrage de l'accès distant). La valeur devient donc $KeyNEW

Le write-host est uniquement là pour le debug (vous pouvez tester cette partie du script sans aucune crainte car il n'y a aucune modification de faite sur le User.

Avant désactivation de mon accès :

Après désactivation de mon accès :