Infraestrutura de Dispositivo Virtual Não Persistente (NP-VDI)
O NP-VDI permite que suas equipes de TI provisionem rapidamente desktops virtuais juntamente com dispositivos físicos, tudo a partir de uma única plataforma unificada. O gerenciamento automatizado integrado economiza tempo, reduz a sobrecarga manual e obtém controles abrangentes de ponto de extremidade em ambientes de nuvem.
Fluxo de trabalho do recurso
Implantação de Agente na Imagem-Base:
-
O agente está instalado (não registrado) em uma VM limpa.
-
O agente é então registrado manualmente como “imagem-base” usando as ferramentas de linha de comando fornecidas.
Selando a imagem-base:
-
Uma vez que o agente de imagem-base tenha se registrado e a configuração seja validada, a VM é “selada” por meio da linha de comando.
Criando Instâncias:
-
Novas instâncias de NP-VDI podem ser criadas a partir da imagem-base, normalmente gerando um novo endereço MAC para cada sessão.
-
O Ivanti Neurons detecta e rastreia esses pontos de extremidade exclusivos e de curto prazo gerenciados sob a imagem-base.
Gerenciamento de Política:
-
As alterações de política podem ser feitas no nível da imagem-base. Todas as instâncias geradas herdam a política aplicada mais recente no próximo check-in.
Etapa 1: Preparar a imagem-base
Para preparar a imagem-base, siga estas etapas:
- Navegue até Agente > Implantação de Agente > Instalação Manual.
- Na guia Instalação Manual, escolha uma política de agente e uma chave de inscrição.
- Selecione Windows. Então, escolha um Modo de Instalação e clique em Baixar.
O instalador do agente será baixado.Esta ação baixa dois arquivos. Salve o instalador com o nome de arquivo "IvantiCloudAgent.exe.options". Este arquivo será usado para a instalação.
- Instale o agente NP-VDI baixado.
Para instalar o agente:- Renomeie o arquivo IvantiCloudAgent.exe.options associado antes da instalação.
- Execute o instalador. Quando a opção chave de ativação ou cookie aparecer e clique em Cancelar.
Isso instala o agente no ponto de extremidade sem registrá-lo no locatário.
- Registre o agente como uma imagem-base. Para registrar como imagem-base, execute os seguintes comandos, como administrador, no local de instalação do agente:
STAgentCtl.exe register --asBaseImage <Base Image Name> --instanceIdType MacAddress --enrollmentkey "%enrollmentkey%" --baseurl https://agentreg.ivanticloud.com
No comando acima:
<Base Image Name> é o nome do dispositivo de imagem-base.
%enrollmentkey% é uma combinação de tenantid_activationkey.
instanceIdType pode ser "MacAddress", "HostName" ou “Custom”. Isso é usado como o sinalizador exclusivo para identificação da instância.
Se "Custom" for usado, uma opção tagList contendo uma lista separada por vírgulas de etiquetas personalizadas pode ser especificada para identificar esse agente. Para obter mais informações sobre etiquetas personalizadas, consulte a Lista de Etiqueta Personalizadas e a seção Atualizar Etiquetas.
Tanto o tenantid quanto a activationkey podem ser encontrados no arquivo .options associado, baixado juntamente com o agente, conforme exibido no exemplo abaixo:
tenantid = 11111111-1111-1111-1111-4gc02d5b0f0d
activationkey = 9aI7SOQNybweiM2QKI7kcqIG8ufUFU21AvZwJwAEx6C-SAO5UGK62YkEgm89kvC2m-xwLesZA4t1_TBtEjIQMVaBU0KsVe-V60ZLBwWu83YREcUp3diAFvHjBvLtkxT3
cloudhost=https:agentreg.ivanticlouddev.comA chave de inscrição para o código acima é:
%enrollmentkey% = 11111111-1111-1111-1111-4gc02d5b0f0d_9aI7SOQNybweiM2QKI7kcqIG8ufUFU21AvZwJwAEx6C-SAO5UGK62YkEgm89kvC2m-xwLesZA4t1_TBtEjIQMVaBU0KsVe-V60ZLBwWu83YREcUp3diAFvHjBvLtkxT3A linha de comando para registrar um dispositivo com o locatário de exemplo para uma imagem-base nomeada “Win11” serão:
STAgentCtl.exe register --asBaseImage Win11 --instanceIdType MacAddress --enrollmentkey “11111111-1111-1111-1111-4gc02d5b0f0d_9aI7SOQNybweiM2QKI7kcqIG8ufUFU21AvZwJwAEx6C-SAO5UGK62YkEgm89kvC2m-xwLesZA4t1_TBtEjIQMVaBU0KsVe-V60ZLBwWu83YREcUp3diAFvHjBvLtkxT3" --baseurl https://agentreg.ivanticloud.com
- Para atualizar a imagem-base:
- Baixe o script do PowerShell do portal da comunidade da Ivanti: Ivanti-Neurons -Non-Persistent-VDI - Agent Script.
Antes de executar o script do PowerShell, verifique se o administrador tem permissão para executá-lo na imagem-base, pois a política de execução no ponto de extremidade pode bloqueá-lo:
Para verificar, use o comando "Get-ExecutionPolicy".
Para alterar, use o comando "Set-ExecutionPolicy RemoteSigned".
- Se o script for executado sem nenhum parâmetro, o script tentará o seguinte:
- Retirar o selo do agente.
- Executar atualizações para agentes e mecanismos.
- Selar o agente novamente.
- Se o agente ainda não estiver selado, ele deve permanecer sem o selo após a atualização. Passe o parâmetro "DoNotSeal" para executar todas as mesmas etapas, exceto selar a imagem.
- O tempo limite padrão para atualizações é de 300 segundos. Você pode alterar o período de tempo fornecendo o argumento“-TimeoutSec”.
Para referência adicional, uma cópia do script pode ser acessada na seção Anexo.
- Para preparar a imagem-base:
- Execute o comando "STAgentCtl.exe prepareImage" para tornar uma imagem-base selada e não persistente pronta para NP-VDI.
Este comando é obrigatório, interrompe todos os serviços e exclui todos os dados relacionados ao ID do agente atual da imagem-base. Quando a instância não persistente é inicializada, o serviço é reiniciado.O ID do agente mudará com cada instância não persistente criada a partir da imagem-base.
- Use os seguintes comandos para selar manualmente a imagem-base (fora do script de atualização):
- Para selar manualmente a imagem-base, insira "STAgentCtl.exe seal".
Use o comando "unseal" para retirar o selo da imagem. Esta configuração permanece ativa até que um sistema reinicie ou o comando "Seal" seja usado.
- Para selar manualmente a imagem-base, insira "STAgentCtl.exe seal".
- Execute o comando "STAgentCtl.exe prepareImage" para tornar uma imagem-base selada e não persistente pronta para NP-VDI.
- (Opcional) Prepare a imagem para ser usada com "sysprep".
Se a preparação não persistente da área de trabalho incluir um estágio sysprep, ela removerá a chave privada do certificado do agente do armazenamento de certificados. Para resolver esse problema, siga estas etapas:O administrador deve fornecer suas próprias senhas de exportação do certificado; caso contrário, este processo irá falhar.
- Localize o número de série do certificado usando o comando certutil -store “Ivanti Cloud Agent Agent”.
Esse comando lista o certificado no armazenamento de certificados do agente. - Após executar o comando “stagentctl prepareImage” na Etapa 7, você pode exportar o certificado do agente usando o seguinte comando:
certutil -exportPFX -privatekey -p "%pfxpass%" “Ivanti Cloud Agent Agent” %serialnumber% "%ProgramFiles%\Ivanti\Ivanti Cloud Agent\agent.pfx" NoChain,NoRoot
No comando acima:
%pfxpass% é uma senha fornecida pelo administrador.
%serialnumber% é o número de série localizado do certificado do agente.
- Faça o download do script SetupComplete.cmd disponível no site da comunidade da Ivanti aqui: restaurar chave privada do script de arquivo .pfx exportado.
- Edite o script SetupComplete.cmd e atualize a senha para corresponder à senha usada para exportar o certificado usado na Etapa 2.
- Armazene o script em %WINDIR%\Setup\Scripts\SetupComplete.cmd na imagem-base.
O script será executado automaticamente assim que a configuração do Windows for concluída (o que acontecerá na primeira vez que o dispositivo for inicializado após o sysprep).Essa execução restaurará a chave privada do arquivo .pfx exportado e excluirá tanto o arquivo .pfx quanto o próprio script, evitando que o segredo seja exposto para as instâncias não persistentes.
O certificado com a UO em questão “ST Agent” (por exemplo, "Subject: OU=ST Agent, CN=011472EFB12BABF06122F2903BBE12AC4E32EBFE5082”) deve ser exportado, usando o número de série correspondente dessa entrada.
- Localize o número de série do certificado usando o comando certutil -store “Ivanti Cloud Agent Agent”.
Etapa 2: Criar e testar instâncias NP-VDI
Para gerar uma nova instância a partir da imagem-base, siga estas etapas:
-
Certifique-se de que um novo endereço MAC esteja atribuído a cada nova instância (para garantir que a opção instanceIdType MacAddress funcione).
Como alternativa, certifique-se de que um nome de host ou etiqueta diferente seja utilizado. -
Inicie a instância de máquina virtual e confirme se a instância aparece na IU do Neurons como um ponto de extremidade NP-VDI exclusivo. Acesse a seção Agentes > Gerenciamento de Agentes da interface do Ivanti Neurons para fazê-lo.
Uma nova coluna Tipo de VDI estará disponível, indicando se o dispositivo é um dispositivo Imagem-base, Não persistente ou Persistente. -
Cada ponto de extremidade do agente agora está vinculado da página Gerenciamento de Agentes à página Dispositivos. Clique no nome do ponto de extremidade do agente para abrir uma nova janela mostrando o dispositivo na exibição Dispositivos.
-
Clique na opção Instâncias vinculadas para exibir todas as instâncias criadas a partir desta imagem-base.
As Instâncias Não Persistentes serão marcadas como Não Persistentes na exibição Dispositivos.
Etapa 3: Reatribuição de política com NP-VDI
Para reatribuir uma política à imagem-base diretamente da interface do Ivanti Neurons, siga estas etapas:
-
Navegue até Agentes > Políticas do agente.
-
Selecione a imagem-base e escolha Reatribuir política no menu Ações.
-
Escolha a política a ser reatribuída e clique em Salvar.
Isso reatribui a política. Após a política ser reatribuída à imagem-base, todas as instâncias de VDI não persistentes herdarão a política na próxima vez que fizerem check-in (que é a cada 200 min por padrão). -
Valide se as novas instâncias herdam a política atualizada após o check-in, usando a interface Agentes ou Gerenciamento de Agentes Ivanti Neurons ou a partir da própria imagem não persistente, usando a linha de comando "Stagentctl status".
Não é possível executar ações de reinicialização em uma instância NP-VDI. Isso redefiniria o dispositivo para seu estado inicial, potencialmente fazendo com que os usuários perdessem o trabalho que concluíram durante suas sessões.
Além disso, as Ações disponíveis na exibição Dispositivos para instâncias não persistentes não contêm ações de reinicialização.
Comandos STAgentCtle.exe adicionais
Você pode usar os seguintes comandos adicionais:
-
Para abrir o agente base para atualizações, insira o comando "Stagentctl.exe unseal".
-
Para forçar a linha de comando a esperar até que a atualização seja concluída antes de retornar o controle, insira o comando "Stagentctl.exe update –wait".
O comando "wait" pode encontrar problemas quando o agente é atualizado, pois requer que os executáveis do agente estejam em execução, o que leva à necessidade de uma reinicialização após a atualização. Para evitar esse problema, a Ivanti oferece um script do PowerShell que permite que um comando de atualização síncrona seja executado.
-
Para fechar o agente base para atualizações, insira o comando "Stagentclt.exe seal".
Lista de etiqueta personalizada
Uma lista de etiqueta personalizada é uma coleção de etiquetas definida pelo usuário que pode ser atribuída a pontos de extremidade no Ivanti Neurons, incluindo instâncias NP-VDI. As etiquetas personalizadas ajudam a classificar, organizar e identificar dispositivos com base em requisitos comerciais, operacionais ou técnicos.
Por exemplo, usar a etiqueta "Sales-[MacAddress]" gera uma etiqueta exclusiva para cada dispositivo substituindo [MacAddress] pelo endereço MAC atual do dispositivo. Essa funcionalidade é particularmente útil para gerar etiquetas exclusivas para instâncias VDI não persistentes.
Use a seguinte sintaxe para fazer referência a atributos do dispositivo e a variáveis de ambiente:
-
Para fazer referência ao endereço MAC, use "[MacAddress]"
-
Para fazer referência ao nome do host, use "[HostName]"
-
<name>Para fazer referência a uma variável de ambiente, use "[env:]"
<name>Onde é o nome da variável ambiente que diferencia maiúsculas de minúsculas.
Atualizar Etiquetas
As etiquetas atribuídas durante o registro da imagem-base permanecem estáticas para todas as instâncias associadas. Se você precisar atualizar as etiquetas, registrar novamente/selar a imagem-base ou usar a automação para atribuir etiquetas com base no critério atual após a implementação da VM.
Apêndice
.SYNOPSIS
Atualiza um agente não persistente, aguardando a atualização concluir e, opcionalmente, sela o agente.
.PARAMETER TimeoutSec
Tempo limite total em segundos.
.PARAMETER UpgradeCode
Código de atualização do agente que está sendo atualizado.
.PARAMETER DoNotSeal
Este parâmetro especifica para não selar o agente após a atualização.
#>
parâmetro
(
[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 "Tempo limite aguardando todas os atualizadores serem concluídos."
}
function Get-AgentVersionFromManifest([string] $manifestPath, [string] $platformKey)
{
if (-not (Test-Path $manifestPath))
{
throw "Não foi possível localizar o manifesto em '$manifestPath'."
}
[xml]$manifestXml = Get-Content $manifestPath
$agentFile = $manifestXml.manifest.files.file | Where-Object { $_.key -eq $platformKey }
if (-not ($agentFile))
{
throw "Entrada de agente com chave='$platformKey' não encontrada."
}
if (-not ($agentFile.version))
{
throw "Não foi possível localizar a versão do agente no manifesto."
}
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 "Agente instalado não encontrado."
}
if (-not ($agentObject.Version))
{
throw "Versão do agente instalada não encontrada."
}
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 "Aguardando o tempo limite da atualização do agente."
}
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 "Não foi possível executar check-in devido ao curto tempo limite."
}
& $agentCtlPath update --checkin --wait $timeoutSec
if (-not $?)
{
throw "Falha na operação de check-in."
}
& $agentCtlPath update --all
if (-not $?)
{
throw "Falha na operação de atualização."
}
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 "Não foi possível executar a atualização final devido ao curto tempo limite."
}
& $agentCtlPath update --all --wait $timeoutSec
if (-not $?)
{
throw "Falha na operação de atualização final."
}
}
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 "Código de atualização '$upgradeCode' não encontrado."
}
if ($productCode.Count -gt 1)
{
throw "Múltiplos produtos com o mesmo código de atualização '$upgradeCode' foram encontrados."
}
return [guid]::Parse($productCode)
}
function Get-AgentEnvironment([string] $installDirPath)
{
$configPath = Join-Path $installDirPath "AgentEnvironment.config"
if (-Not (Test-Path $configPath))
{
throw "Arquivo de configuração não encontrado em $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 "O produto GUID não foi encontrado."
}
return $productObject.InstallLocation
}
$timeoutDateTime = (Get-Date).AddSeconds($TimeoutSec)
Write-Host "Reunindo informações..."
try
{
$agentProductCode = Get-ProductCode -UpgradeCode $UpgradeCode
$installDirPath = Get-InstallLocation -ProductCode $agentProductCode
Write-Host " Install directory: $installDirPath"
$agentEnvironment = Get-AgentEnvironment -InstallDirPath $installDirPath
$dataDirPath = $agentEnvironment.agentEnvironment.agentDataDirectory
Write-Host " Data directory: $dataDirPath"
$regPath = Join-Path "HKLM:" $agentEnvironment.agentEnvironment.registryPath
Write-Host " Registry key: $regPath"
$platformKey = Get-ItemProperty -Path $regPath -Name "PlatformManifestKey" -ErrorAction Stop | Select-Object -ExpandProperty "PlatformManifestKey" -ErrorAction Stop
Write-Host " Platform key: $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 "ERRO: o tempo limite expirou antes que a atualização do agente pudesse começar."
exit -1
}
Write-Host "Deslacrando o agente..."
& $agentCtlPath unseal
if (-not $?)
{
Write-Error "ERRO: não é possível realizar a operação de deslacramento."
exit -1
}
Write-Host "Atualizando o agente..."
$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 "O agente foi atualizado com sucesso."
}
else
{
Write-Error "ERRO: falha na atualização do agente."
}
exit $result
}
Write-Host "Lacrando o agente..."
& $agentCtlPath seal
if (-not $?)
{
Write-Error "ERRO: não é possível lacrar o agente!
exit -1
}
if ($result -eq 0)
{
Write-Host "O agente foi atualizado e lacrado com sucesso."
}
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% Restauração da chave do agente iniciada >> "%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 Falha ao importar a chave do agente >> "%logfile%"
)
ECHO Removendo o arquivo de chave do agente >> "%logfile%"
del "%certFile%" >> "%logfile%" 2>&1
IF %ERRORLEVEL% NEQ 0 (
ECHO Falha ao excluir o arquivo de chave do agente >> "%logfile%"
)
ECHO %date% %time% Restauração da chave do agente concluída >> "%logfile%"
) ELSE (
ECHO %date% %time% Falha na restauração da chave do agente: nenhuma chave do agente encontrada >> "%logfile%"
)
ECHO Removendo o script >> "%logfile%"
del "%scriptPath%" >> "%logfile%" 2>&1
"REM não é possível executar outros comandos a partir deste ponto porque o arquivo de script foi excluído"