Infrastructure de périphériques virtuels non persistants (NP-VDI)
NP-VDI permet à votre équipe IT de provisionner rapidement des postes de travail virtuels en plus des périphériques physiques, le tout depuis une seule plateforme unifiée. Les fonctions intégrées de gestion automatisée permettent de gagner du temps, de réduire les opérations manuelles et de bénéficier d'un contrôle complet du poste client dans un environnement Cloud.
Workflow de fonctions
Agent Deployment (Déploiement d'agent) dans l'image de base :
-
L'agent est installé (non inscrit) dans une VM propre.
-
Vous inscrivez ensuite l'agent manuellement comme « Image de base », à l'aide de l'outil de ligne de commande fourni.
Scellement de l'image de base :
-
Une fois l'agent d'image de base inscrit et la configuration validée, la VM est « scellée » via la ligne de commande.
Génération d'instances :
-
Il est possible de dériver de nouvelles instances NP-VDI à partir de l'image de base, en créant généralement une nouvelle adresse MAC pour chaque session.
-
Ivanti Neurons les détecte et les suit en tant que postes client uniques à court terme gérés sous l'image de base.
Gestion des stratégies :
-
Vous pouvez modifier la stratégie au niveau de l'image de base. Toutes les instances engendrées héritent de la dernière stratégie appliquée, à leur prochaine prise de contact.
Étape 1 : Préparation de l'image de base
Pour préparer l'image de base, procédez comme suit :
- Accédez à Agent > Agent Deployment (Déploiement d'agent) > Installation manuelle.
- Dans l'onglet Installation manuelle, choisissez une stratégie d'agent et une clé d'inscription.
- Sélectionnez Windows. Choisissez ensuite un mode d'installation et cliquez sur Télécharger.
Le programme d'installation de l'agent est téléchargé.Cette action télécharge deux fichiers. Enregistrez le programme d'installation avec le nom de fichier « IvantiCloudAgent.exe.options ». Ce fichier est utilisé pour l'installation.
- Installez l'agent NP-VDI téléchargé.
Pour installer l'agent :- Renommez le fichier IvantiCloudAgent.exe.options associé avant l'installation.
- Exécutez le programme d'installation. Lorsque l'option Clé d'activation ou Cookie s'affiche, cliquez sur Annuler.
Cela installe l'agent sur le poste client sans l'inscrire auprès du locataire.
- Inscrivez l'agent comme image de base. Pour l'inscrire comme image de base, exécutez la commande suivante en tant qu'administrateur, depuis l'emplacement d'installation de l'agent :
STAgentCtl.exe register --asBaseImage <Base Image Name> --instanceIdType MacAddress --enrollmentkey "%enrollmentkey%" --baseurl https://agentreg.ivanticloud.com
Dans la commande ci-dessus :
<Base Image Name> est le nom du périphérique d'image de base.
%enrollmentkey% est une combinaison de tenantid_activationkey.
instanceIdType peut être « MacAddress », « HostName » ou « Custom » (Adresse MAC, Nom d'hôte ou Personnalisé). Cette valeur sert d'indicateur unique pour identifier l'instance.
Si vous utilisez « Personnalisé », vous pouvez spécifier l'option de liste de balises (tagList), qui contient une liste de balises personnalisées séparées par des virgules pour identifier cet agent. Pour en savoir plus sur les balises personnalisées, reportez-vous aux sections « Liste de balises personnalisées » et « Mise à jour des balises ».
La valeur ID de locataire (tenantid) et la clé d'activation (activationkey) se trouvent toutes deux dans le fichier .options associé, téléchargé avec l'agent, comme le montre l'exemple ci-dessous :
tenantid = 11111111-1111-1111-1111-4gc02d5b0f0d
activationkey = 9aI7SOQNybweiM2QKI7kcqIG8ufUFU21AvZwJwAEx6C-SAO5UGK62YkEgm89kvC2m-xwLesZA4t1_TBtEjIQMVaBU0KsVe-V60ZLBwWu83YREcUp3diAFvHjBvLtkxT3
cloudhost=https:agentreg.ivanticlouddev.comLa clé d'inscription correspondant au code ci-dessus est :
%enrollmentkey% = 11111111-1111-1111-1111-4gc02d5b0f0d_9aI7SOQNybweiM2QKI7kcqIG8ufUFU21AvZwJwAEx6C-SAO5UGK62YkEgm89kvC2m-xwLesZA4t1_TBtEjIQMVaBU0KsVe-V60ZLBwWu83YREcUp3diAFvHjBvLtkxT3La ligne de commande permettant d'inscrire un périphérique avec cet exemple de locataire pour l'image de base nommée « Win11 » est la suivante :
STAgentCtl.exe register --asBaseImage Win11 --instanceIdType MacAddress --enrollmentkey “11111111-1111-1111-1111-4gc02d5b0f0d_9aI7SOQNybweiM2QKI7kcqIG8ufUFU21AvZwJwAEx6C-SAO5UGK62YkEgm89kvC2m-xwLesZA4t1_TBtEjIQMVaBU0KsVe-V60ZLBwWu83YREcUp3diAFvHjBvLtkxT3" --baseurl https://agentreg.ivanticloud.com
- Pour mettre à jour l'image de base :
- Téléchargez le script PowerShell depuis le portail de la communauté Ivanti : Ivanti-Neurons -Non-Persistent-VDI - Agent Script.
Avant d'exécuter le script PowerShell, vérifiez que l'Admin dispose des permissions nécessaires pour exécuter cette opération sur l'image de base, car la stratégie d'exécution sur le poste client peut bloquer la procédure :
Pour vérifier, utilisez la commande « Get-ExecutionPolicy ».
Pour apporter une modification, utilisez la commande « Set-ExecutionPolicy RemoteSigned ».
- Si le script s'exécute sans aucun paramètre, il tente d'effectuer les opérations suivantes :
- Desceller l'agent.
- Exécuter des mises à jour pour les agents et les moteurs.
- Resceller l'agent.
- Si l'agent est déjà descellé et qu'il doit rester descellé après la mise à jour. Transmettez le paramètre « DoNotSeal » (Ne pas sceller) pour exécuter les mêmes étapes, sauf celle de scellement de l'image.
- Le délai par défaut pour les mises à jour est de 300 secondes. Vous pouvez modifier cette valeur en transmettant l'argument « -TimeoutSec ».
Pour en savoir plus, vous pouvez accéder à une copie du script dans la section Annexe.
- Pour préparer l'image de base :
- Exécutez la commande « STAgentCtl.exe prepareImage » pour préparer une image de base scellée non persistante pour NP-VDI.
Cette commande est obligatoire. Elle arrête tous les services et supprime toutes les données liées à l'ID d'agent réel de l'image de base. Lorsque l'instance non persistante s'amorce, les services sont redémarrés.L'ID d'agent change à chaque instance non persistante générée à partir de l'image de base.
- Utilisez les commandes suivantes pour sceller manuellement l'image de base (en dehors du script de mise à niveau) :
- Pour sceller manuellement l'image de base, entrez « STAgentCtl.exe seal ».
Utilisez la commande « Unseal » pour desceller l'image. Elle reste active jusqu'au redémarrage du système ou à l'utilisation de la commande « Seal » (Sceller).
- Pour sceller manuellement l'image de base, entrez « STAgentCtl.exe seal ».
- Exécutez la commande « STAgentCtl.exe prepareImage » pour préparer une image de base scellée non persistante pour NP-VDI.
- (Facultatif) Préparez l'image pour utilisation avec « sysprep ».
Si la préparation du poste de travail non persistant inclut une étape sysprep, elle supprime la clé privée du certificat d'agent dans le magasin de certificats. Pour résoudre ce problème, procédez comme suit :L'administrateur doit fournir son propre mot de passe d'exportation de certificat ; sinon, le processus échoue.
- Localisez le numéro de série du certificat avec la commande certutil -store "Ivanti Cloud Agent Agent".
Cette commande répertorie le certificat dans le magasin de certificats d'agent. - Après avoir exécuté la commande « stagentctl prepareImage » à l'étape 7, vous pouvez exporter le certificat d'agent à l'aide de la commande suivante :
certutil -exportPFX -privatekey -p "%pfxpass%" “Ivanti Cloud Agent Agent” %serialnumber% "%ProgramFiles%\Ivanti\Ivanti Cloud Agent\agent.pfx" NoChain,NoRoot
Dans la commande ci-dessus :
%pfxpass% est un mot de passe fourni par l'administrateur.
%serialnumber% est le numéro de série du certificat d'agent.
- Téléchargez le script SetupComplete.cmd, disponible sur le site Web de la communauté Ivanti à l'adresse suivante : « Restaurer la clé privée depuis le script de fichier .pfx exporté ».
- Modifiez le script SetupComplete.cmd et mettez à jour le mot de passe pour qu'il corresponde à celui ayant servir à exporter le certificat, utilisé à l'étape 2.
- Stockez le script sous %WINDIR%\Setup\Scripts\SetupComplete.cmd dans l'image Gold.
Le script s'exécute automatiquement une fois la configuration Windows terminée (ce qui se produit au premier amorçage du périphérique après sysprep).Cela restaure la clé privée à partir du fichier .pfx exporté, puis supprime à la fois ce fichier .pfx et le script proprement dit, pour éviter toute fuite du secret dans les instances non persistantes.
Le certificat portant l'objet « OU "ST Agent" » (par ex. "Subject: OU=ST Agent, CN=011472EFB12BABF06122F2903BBE12AC4E32EBFE5082") doit être exporté, en utilisant le numéro de série correspondant depuis cette entrée.
- Localisez le numéro de série du certificat avec la commande certutil -store "Ivanti Cloud Agent Agent".
Étape 2 : Création et test des instances NP-VDI
Pour générer une nouvelle instance depuis l'image de base, procédez comme suit :
-
Vérifiez qu'une nouvelle adresse MAC est bien affectée à chaque nouvelle instance (pour garantir que l'option instanceIdType MacAddress fonctionne).
Sinon, veillez à utiliser un autre nom d'hôte ou une autre balise. -
Démarrez l'instance de machine virtuelle et vérifiez qu'elle apparaît dans l'interface Neurons en tant que poste client NP-VDI unique. Pour ce faire, accédez à la section Agents > Gestion des agents de l'interface Ivanti Neurons.
La nouvelle colonne Type VDI est disponible. Elle indique si le périphérique est de type Image de base, Non persistant ou Persistant. -
Chaque poste client d'agent est désormais lié de la page Gestion des agents à la page Périphériques. Cliquez sur le nom de poste client d'agent pour ouvrir une nouvelle fenêtre montrant le périphérique dans la vue Périphériques.
-
Cliquez sur l'option Instances liées pour afficher toutes les instances engendrées depuis cette image de base.
Les instances non persistantes sont marquées Non persistant dans la vue Périphériques.
Étape 3 : Réaffectation d'une stratégie avec NP-VDI
Pour réaffecter une stratégie à l'image de base directement depuis l'interface Ivanti Neurons, procédez comme suit :
-
Accédez à Agents > Stratégies d'agent.
-
Sélectionnez l'image de base et choisissez Réaffecter une stratégie dans le menu Actions.
-
Choisissez la stratégie à réaffecter et cliquez sur Enregistrer.
Cela réaffecte la stratégie. Une fois la stratégie réaffectée à l'image de base, toutes les instances VDI non persistantes héritent de cette stratégie à leur prochaine prise de contact (par défaut, toutes les 200 minutes). -
Vérifiez que les nouvelles instances héritent bien de la stratégie mise à jour après leur prise de contact, soit dans l'interface Agents ou Gestion des agents d'Ivanti Neurons, soit à partir de l'image non persistante proprement dite, avec la ligne de commande « Stagentctl status ».
Il n'est pas possible d'exécuter des actions de redémarrage sur une instance NP-VDI. Cela réinitialiserait l'état initial du périphérique et potentiellement, entraînerait de tout le travail effectué pendant sa session.
De plus, les actions disponibles dans la vue Périphériques pour les instances non persistantes n'incluent aucune action de redémarrage.
Commandes STAgentCtle.exe supplémentaires
Vous pouvez utiliser les commandes supplémentaires suivantes :
-
Pour ouvrir l'agent de base en vue d'une mise à jour, entrez la commande « Stagentctl.exe unseal ».
-
Pour forcer la ligne de commande à attendre que la mise à jour soit terminée avant de reprendre le contrôle, entrez la commande « Stagentctl.exe update -wait ».
La commande Attendre (-wait) peut rencontrer des problèmes lors de la mise à jour de l'agent, car elle nécessite l'exécution des exécutables d'agent et donc, un redémarrage après la mise à jour. Pour éviter ce problème, Ivanti propose un script PowerShell qui permet d'exécuter une commande de mise à jour synchrone.
-
Pour fermer l'agent de base et interdire les mises à jour, entrez la commande « Stagentclt.exe seal ».
Liste de balises personnalisées
Une liste de balises personnalisées est une collection définie par l'utilisateur de balises pouvant être affectées aux postes client dans Ivanti Neurons, y compris aux instances NP-VDI. Les balises personnalisées permettent de classer, d'organiser et d'identifier les périphériques en fonction des besoins commerciaux, opérationnels ou techniques.
Par exemple, l'utilisation de la balise « Sales-[MacAddress] » génère une balise unique pour chaque périphérique en remplaçant [MacAddress] par l'adresse MAC réelle du périphérique. Cette fonction est particulièrement utile pour générer des balises uniques pour les instances VDI non persistantes.
Utilisez la syntaxe suivante pour référencer les attributs de périphérique et les variables d'environnement :
-
Pour référencer l'adresse MAC, utilisez [MacAddress]
-
Pour référencer le nom d'hôte, utilisez [HostName]
-
Pour référencer une variable d'environnement, utilisez [env:<name>]
Où <name> est le nom (sensible à la casse) de la variable d'environnement.
Mettre à jour les balises
Les balises affectées lors de l'inscription de l'image de base restent statiques pour toutes les instances associées. Si vous devez mettre à jour des balises, réinscrivez/rescellez l'image de base ou utilisez l'automatisation pour affecter des balises en fonction des critères actuels après le déploiement de la VM.
Annexe
.SYNOPSIS
Met à jour un agent non persistant, attend que la mise à jour soit terminée, puis (si nécessaire) scelle l'agent.
.PARAMETER TimeoutSec
Délai total en secondes.
.PARAMETER UpgradeCode
Code de mise à niveau de l'agent en cours de mise à jour.
.PARAMETER DoNotSeal
Ce paramètre spécifie de ne pas sceller l'agent après la mise à jour.
#>
param
(
[int] $TimeoutSec = 300,
[guid] $UpgradeCode = "{0C5D7E9C-0424-462D-A570-2A7469EE3739}", # Neurons Agent
[switch] $DoNotSeal
)
function Check-UpdatersComplete
{
$updaters = Get-Process -Name "STAgentUpdater" -ErrorAction SilentlyContinue
return ($updaters.Count -eq 0)
}
function Wait-UpdatersComplete([DateTime] $timeoutDateTime, [int] $checkIntervalSec)
{
while ((Get-Date) -lt $timeoutDateTime)
{
if (Check-UpdatersComplete)
{
return
}
Start-Sleep -Seconds $checkIntervalSec
}
throw "Délai d'attente de la fin de toutes les mises à jour."
}
function Get-AgentVersionFromManifest([string] $manifestPath, [string] $platformKey)
{
if (-not (Test-Path $manifestPath))
{
throw "Manifeste introuvable dans '$manifestPath'."
}
[xml]$manifestXml = Get-Content $manifestPath
$agentFile = $manifestXml.manifest.files.file | Where-Object { $_.key -eq $platformKey }
if (-not ($agentFile))
{
throw "Entrée d'agent avec key='$platformKey' introuvable."
}
if (-not ($agentFile.version))
{
throw "Version d'agent introuvable dans le manifeste."
}
return [version]::Parse($agentFile.version)
}
function Get-CurrentAgentVersion([guid] $agentUpgradeCode)
{
$agentProductCode = Get-ProductCode -UpgradeCode $agentUpgradeCode
$agentObject = Get-WmiObject -Class Win32_Product | Where-Object { [guid]::Parse($_.IdentifyingNumber) -eq $agentProductCode }
if (-not ($agentObject))
{
throw "Agent installé introuvable."
}
if (-not ($agentObject.Version))
{
throw "Version de l'agent installé introuvable."
}
return [version]::Parse($agentObject.Version)
}
function Check-AgentUpToDate([string] $manifestPath, [guid] $agentUpgradeCode, [string] $platformKey)
{
$manifestVersion = Get-AgentVersionFromManifest -ManifestPath $manifestPath -PlatformKey $platformKey
$currentVersion = Get-CurrentAgentVersion -AgentUpgradeCode $agentUpgradeCode
return ($currentVersion -ge $manifestVersion)
}
function Wait-AgentUpdated([DateTime] $timeoutDateTime, [int] $checkIntervalSec, [string] $manifestPath, [guid] $agentUpgradeCode, [string] $platformKey)
{
while ((Get-Date) -lt $timeoutDateTime)
{
if (Check-AgentUpToDate -ManifestPath $manifestPath -AgentUpgradeCode $agentUpgradeCode -PlatformKey $platformKey)
{
return
}
Start-Sleep -Seconds $checkIntervalSec
}
throw "Délai d'attente de mise à jour de l'agent écoulé."
}
function Update-Agent([DateTime] $timeoutDateTime, [string] $manifestPath, [guid] $agentUpgradeCode, [string] $agentCtlPath, [string] $platformKey)
{
$timeoutSec = [math]::Ceiling(($timeoutDateTime - (Get-Date)).TotalSeconds)
if ($timeoutSec -le 0)
{
throw "Prise de contact impossible car le délai est trop court."
}
& $agentCtlPath update --checkin --wait $timeoutSec
if (-not $?)
{
throw "Échec de l'opération de prise de contact."
}
& $agentCtlPath update --all
if (-not $?)
{
throw "Échec de l'opération de mise à jour."
}
Wait-AgentUpdated -TimeoutDateTime $timeoutDateTime -CheckIntervalSec 1 -ManifestPath $manifestPath -AgentUpgradeCode $agentUpgradeCode -PlatformKey $platformKey
Wait-UpdatersComplete -TimeoutDateTime $timeoutDateTime -CheckIntervalSec 1
$timeoutSec = [math]::Ceiling(($timeoutDateTime - (Get-Date)).TotalSeconds)
if ($timeoutSec -le 0)
{
throw "Impossible d'exécuter la mise à jour finale car le délai est trop court."
}
& $agentCtlPath update --all --wait $timeoutSec
if (-not $?)
{
throw "Échec de l'opération de mise à jour finale."
}
}
function Get-ProductCode([guid] $upgradeCode)
{
$upgradeCodeStr = $upgradeCode.ToString("B") # Format as {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
$wmiFilter = "Property='UpgradeCode' AND Value='$upgradeCodeStr'"
$productCode = @(Get-WmiObject -Class Win32_Property -Filter $wmiFilter).ProductCode
if ($productCode.Count -eq 0)
{
throw "Code de mise à niveau '$upgradeCode' introuvable."
}
if ($productCode.Count -gt 1)
{
throw "Plusieurs produits trouvés avec le même code de mise à niveau '$upgradeCode'."
}
return [guid]::Parse($productCode)
}
function Get-AgentEnvironment([string] $installDirPath)
{
$configPath = Join-Path $installDirPath "AgentEnvironment.config"
if (-Not (Test-Path $configPath))
{
throw "Fichier de configuration introuvable dans $configPath."
}
[xml]$agentEnvironment = Get-Content $configPath
return $agentEnvironment
}
function Get-InstallLocation([guid] $productCode)
{
$productObject = Get-WmiObject -Class Win32_Product | Where-Object { [guid]::Parse($_.IdentifyingNumber) -eq $productCode }
if ($null -eq $productObject)
{
throw "GUID de produit introuvable."
}
return $productObject.InstallLocation
}
$timeoutDateTime = (Get-Date).AddSeconds($TimeoutSec)
Write-Host "Collecte des informations..."
try
{
$agentProductCode = Get-ProductCode -UpgradeCode $UpgradeCode
$installDirPath = Get-InstallLocation -ProductCode $agentProductCode
Write-Host " Répertoire d'installation : $installDirPath"
$agentEnvironment = Get-AgentEnvironment -InstallDirPath $installDirPath
$dataDirPath = $agentEnvironment.agentEnvironment.agentDataDirectory
Write-Host " Répertoire de données : $dataDirPath"
$regPath = Join-Path "HKLM:" $agentEnvironment.agentEnvironment.registryPath
Write-Host " Clé de registre : $regPath"
$platformKey = Get-ItemProperty -Path $regPath -Name "PlatformManifestKey" -ErrorAction Stop | Select-Object -ExpandProperty "PlatformManifestKey" -ErrorAction Stop
Write-Host " Clé de plateforme : $platformKey"
$agentCtlPath = Join-Path $installDirPath "STAgentCtl.exe"
$manifestPath = Join-Path $dataDirPath "manifest.xml"
}
catch
{
Write-Error "ERROR: $_"
exit -1
}
if ((Get-Date) -gt $timeoutDateTime)
{
Write-Error "ERREUR : Délai expiré avant que la mise à jour de l'agent puisse commencer."
exit -1
}
Write-Host "Descellement de l'agent..."
& $agentCtlPath unseal
if (-not $?)
{
Write-Error "ERREUR : Opération de descellement impossible."
exit -1
}
Write-Host "Mise à jour de l'agent..."
$result = -1
try
{
Update-Agent -TimeoutDateTime $timeoutDateTime -ManifestPath $manifestPath -AgentUpgradeCode $UpgradeCode -AgentCtlPath $agentCtlPath -PlatformKey $platformKey
$result = 0
}
catch
{
Write-Error "ERROR: $_"
}
if ($DoNotSeal)
{
if ($result -eq 0)
{
Write-Host "L'agent a été mis à jour avec succès."
}
else
{
Write-Error "ERREUR : Échec de la mise à jour de l'agent."
}
exit $result
}
Write-Host "Scellement de l'agent..."
& $agentCtlPath seal
if (-not $?)
{
Write-Error "ERREUR : Impossible de sceller l'agent !"
exit -1
}
if ($result -eq 0)
{
Write-Host "L'agent a été mis à jour et scellé avec succès."
}
exit $result
(@ECHO OFF
set pw=supersecret
set logfile=C:\ProgramData\Ivanti\Ivanti Cloud Agent\Logs\agentkeyrestore.log
set certFile=C:\Program Files\Ivanti\Ivanti Cloud Agent\agent.pfx
set scriptPath=%0%
ECHO %date% %time% Restauration de la clé d'agent démarrée >> "%logfile%"
IF EXIST "%certFile%" (
certutil -f -p "%pw%" -privatekey -importPFX "Ivanti Cloud Agent Agent" "%certFile%" NoCert,NoExport >> "%logfile%" 2>&1
IF %ERRORLEVEL% NEQ 0 (
ECHO Échec de l'importation de la clé d'agent >> "%logfile%"
)
ECHO Suppression du fichier de clé d'agent >> "%logfile%"
del "%certFile%" >> "%logfile%" 2>&1
IF %ERRORLEVEL% NEQ 0 (
ECHO Impossible de supprimer le fichier de clé d'agent >> "%logfile%"
)
ECHO %date% %time% Restauration de la clé d'agent terminée >> "%logfile%"
) ELSE (
ECHO %date% %time% Échec de la restauration de la clé d'agent : Aucun fichier de clé d'agent trouvé >> "%logfile%"
)
ECHO Suppression du script >> "%logfile%"
del "%scriptPath%" >> "%logfile%" 2>&1
"REM Impossible d'exécuter une autre commande à partir de ce point, car le fichier de script a été supprimé"