Как произвести снятие назначения пользователя и последующее выключение виртуальной машины по действию Logoff (Logout)?

В данной статье рассматривается, как произвести снятие назначения (отвязку) пользователей, выключение, удаление виртуальных машин и другие действия, которые выполняются с помощью доставки сообщений из гостевой операционной системы на внешний источник, при выполнении действия Logoff (Logout) для пользователя.

Пример для операционной системы Windows

  1. Установите зависимости. Скачайте архив :https://curl.se/windows/dl-7.85.0_1/curl-7.85.0_1-win64-mingw.zip.

    Разархивируйте архив в директорию C:/Programm Files.

  2. Установите менеджер пакетов Chocolatey. Для этого откройте командную строку и выполните следующую команду:

    @"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
    
  3. Установите с помощью Chocolatey jQuery. Для этого в командной строке выполните:

    chocolatey install -y jq
    
  4. Перезагрузите виртуальную машину.

  5. Для рестарта и удаления создайте файл скрипта «Рестарт, удаление виртуальной машины при событии Logout» - logout.bat. Пример скрипта приведен ниже. Поместите в C:\scripts\.

  6. Для логирования создайте файл скрипта «Логирование событий Login/Logout в базе данных» - journal.bat. Пример скрипта приведен ниже. Поместите в C:\scripts\.

    Важно

    Пути нахождения скрипта и файлов токена (см. скрипт) должны быть доступны в правах на создание и редактирование новых файлов. Иначе скрипт не будет отрабатывать, так как при событии Logout он отрабатывает с правами пользователя, а не администратора!

  7. Для запуска скрипта по событию Login/Logout необходимо:

    Нажмите «Пуск» — «Выполнить» — введите gpedit.msc и нажмите «Enter»;

    Перейдите в пункт «User Configuration» — «Windows Settings» — «Scripts (Logon/Logoff)» — «Logoff» и укажите путь к скрипту;

    Перейдите в пункт «User Configuration» — «Windows Settings» — «Scripts (Logon/Logoff)» — «Logon» и укажите путь к скрипту. Учитывайте порядок выполнения скриптов при их установке.

  8. Для автоматического завершения сессии авторизованного пользователя при отключении (по таймауту) необходимо:

    Нажмите «Пуск» - «Выполнить» - введите gpedit.msc.

    Далее настройте следующий параметр: Computer Configuration - Administrative Components - Windows Components - Remote Desktop Services - Remote Desktop Session - Session Time Limits - Set time limit for disconnected sessions - <set timeout> (выбрать желаемое время таймаута).

Пример скрипта для отвязки пользователя от TRS машины и последующего её выключения

Примечание

В скрипте должен использоваться администратор проекта домена или проекта, в котором находится виртуальная машина, так как другие, обычные пользователе не имеют права на выключение и отвязку пользователей от виртуальной машины! Также пользователь должен иметь право на чтение списка пользователей домена.

Текст скрипта:

(# при реализации комментарии стереть)
@echo off

setlocal enableextensions enabledelayedexpansion

rem set variables
# вставить IP контроллера
set controller=10.1.220.31
       # логин
set login=jerry
# пароль
set pass=1pass
       # проект
set tenant=testproject1
set hostname=%computername%
# функция преобразования в нижний регистр. По необходимости использования удалить «rem»
rem call :tolower hostname
# убедиться, что права на создание файлов у пользователей в каталоге есть
# лог скрипта
set logfile=c:\scripts\logout.log
set responsefile=c:\scripts\token.txt
# убедиться, что путь корректный
set curl=c:\progra~1\curl-7.84.0_9-win64-mingw\bin\curl.exe
set json="{\"auth\":{\"identity\":{\"methods\":[\"password\"],\"password\":{\"user\":{\"domain\":{\"name\":\"msk\"},\"name\":\"%login%\",\"password\":\"%pass%\"}}},\"scope\":{\"project\":{\"domain\":{\"name\":\"msk\"},\"name\":\"%tenant%\"}}}}"
set json_adm="{\"auth\":{\"identity\":{\"methods\":[\"password\"],\"password\":{\"user\":{\"domain\":{\"name\":\"msk\"},\"name\":\"jerry\",\"password\":\"13Qwerty\"}}},\"scope\":{\"project\":{\"domain\":{\"name\":\"msk\"},\"name\":\"testproject1\"}}}}"

rem write to log file
echo get command logout %username% at %date% %time% >> %logfile%
rem http request
%curl% -si -X POST -H "Content-type:application/json" -d %json% "http://%controller%:5000/v3/auth/tokens" | findstr X-Subject-Token > %responsefile%

rem get token
set /p response=<%responsefile%
set token=%response:~17%
echo  - get token >> %logfile%

rem get userid
%curl% -s -X GET -H "X-Auth-Token: %token%" -H "Content-type:application/json" "http://%controller%:5000/v3/users" | jq ".users[] | select(.name==\"%username%\").id" > %responsefile%
set /p userid=<%responsefile%
echo  - get id user %username% - %userid% >> %logfile%

rem get tenantid
%curl% -s -X GET -H "X-Auth-Token: %token%" -H "Content-type:application/json" "http://%controller%:5000/v3/projects" | jq ".projects[] | select(.name==\"%tenant%\").id" > %responsefile%
set /p tenantid=<%responsefile%
echo  - get id tenant %tenant% - %tenantid% >> %logfile%

rem http request
%curl% -si -X POST -H "Content-type:application/json" -d %json% "http://%controller%:5000/v3/auth/tokens" | findstr X-Subject-Token > %responsefile%

rem get token
set /p response=<%responsefile%
set token=%response:~17%
echo  - get token >> %logfile%

rem get id vm
%curl% -s -X GET -H "X-Auth-Token: %token%" -H "Content-type:application/json" "http://%controller%:8774/v2.1/servers" | jq ".servers[] | select(.name==\"%hostname%\").id" > %responsefile%
set /p vm=<%responsefile%
echo  - get id vm %hostname% - %vm% >> %logfile%

rem unassign user from vm
%curl% -X DELETE -H "X-Auth-Token: %token%" -H "Content-type:application/json" "http://%controller%:9364/v1/servers/%vm%/users/%userid%" | jq ".users[] | select(.name==\"%username%\").id" > %responsefile%
echo  - unassign user %username% from vm %vm% >> %logfile%

rem poweroff vm
%curl% -s -X POST -H "X-Auth-Token: %token%" -H "Content-type:application/json" -d "{\"os-stop\" : null}" "http://%controller%:8774/v2.1/servers/%vm%/action"
echo  - shutoff vm %vm% >> %logfile%

rem delay and write to log file
timeout 30 > nul
echo after sleping 30 sec %date% %time% >> %logfile%
echo ----- >> %logfile%

rem delete temp files
del %responsefile%
goto :END

:tolower
for %%L in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do set %1=!%1:%%L=%%L!
goto :EOF

:END

Пример скрипта для логирования события Logout в базе данных

Текст скрипта:

(# при реализации комментарии стереть)
@echo off

setlocal enableextensions enabledelayedexpansion

rem set variables
# вставить IP контроллера
set controller=10.1.220.31
# логин
set login=peppa
# пароль
set pass=13Qwerty
       # проект
set tenant=testproject1
set hostname=%computername%
# функция преобразования в нижний регистр. По необходимости использования удалить «rem»
call :tolower hostname
# убедиться, что права на создание файлов у пользователей в каталоге есть
# лог скрипта
set logfile=c:\scripts\journal.log
set responsefile=c:\scripts\token.txt
# убедиться, что путь корректный
set curl=c:\progra~1\curl-7.84.0_9-win64-mingw\bin\curl.exe
set json_adm="{\"auth\":{\"identity\":{\"methods\":[\"password\"],\"password\":{\"user\":{\"domain\":{\"name\":\"msk\"},\"name\":\"%login%\",\"password\":\"%pass%\"}}},\"scope\":{\"domain\":{\"name\":\"msk\"}}}}"

rem write to log file
echo get command logout %username% at %date% %time% >> %logfile%

rem http request
%curl% -si -X POST -H "Content-type:application/json" -d %json_adm% "http://%controller%:5000/v3/auth/tokens" | findstr X-Subject-Token > %responsefile%

rem get token
set /p response=<%responsefile%
set token=%response:~17%
echo  - get token >> %logfile%

rem get ip
for /f "delims=[] tokens=2" %%a in ('ping -4 -n 1 %ComputerName% ^| findstr [') do set ip=%%a

rem get id vm
%curl% -s -X GET -H "X-Auth-Token: %token%" -H "Content-type:application/json" "http://%controller%:8774/v2.1/servers" | jq ".servers[] | select(.name==\"%hostname%\").id" > %responsefile%
set /p vm=<%responsefile%
echo  - get id vm %hostname% - %vm% >> %logfile%

rem add record to journal
set json_journal="{\"journal\":{\"object_id\": \"%vm%\",\"object_type\":\"server\",\"action\":\"logout\",\"status\":\"success\",\"user_name\":\"%username%\",\"message\":\"%ip%\",\"domain_id\":\"d1949bd531b24445921669165cf2813d\"}}"
%curl% -X POST -H "X-Auth-Token: %token%" -H "Content-type:application/json" -d %json_journal% "http://%controller%:9360/v1/journal/"
echo  - add record to journal >> %logfile%

rem write to log file
echo ----- >> %logfile%

rem delete temp files
del %responsefile%
goto :END

:tolower
for %%L in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do set %1=!%1:%%L=%%L!
goto :EOF

:END