blog by ficti0n

среда, 7 сентября 2022 г.

ГитХаб

 Времени вести страничку почти нет. Если будет что то новое, буду выкладывать на ГитХаб https://github.com/volkiam

вторник, 30 июня 2020 г.

Создание заявок в системе GLPI с помощью REST API на Delphi

Для работы понадобилось провести в разрабатываемую программу интеграцию с системой хелпдеска GLPI. Поиск в интернете примеров на Delphi не принес приемлемых результатов и пришлось все писать с нуля. Вот решил поделиться примером создания заявки с прикреплением файла.
P.S. также рекомендую к прочтению вот эту статью, в ней описано GLPI  настраивать для включения REST API

Глобальные переменные и константы:

const
  AppToken = 'hAQiq39NeHWaQ25t6cTkV8762VcHL2Tds7qBuLR4';
  userToken = 'pRHHulWPKXqSrL3xS8vlSCqGIsOu7HWb7rJ3ixI4';

var
  session_token : string;
  GlpiUser, GlpiPassword, GlpiRestUrl : string;

Начинаем все с подключения к GLPI и получения токена сессии:

Function Get_session_token : string;
    var
      IdHTTP: TIdHTTP;
      Answer: string;
      JSON : TJSONObject;
begin
  try

    try
      IdHTTP := TIdHTTP.Create(nil);
      try
        IdHTTP.Request.Connection := 'Keep-Alive';
        Idhttp.HTTPOptions := [hoKeepOrigProtocol,hoForceEncodeParams,hoNoProtocolErrorException,hoWantProtocolErrorContent];
        IdHTTP.Request.ContentType := 'application/json';
        idHttp.Request.BasicAuthentication := true;
        idHttp.Request.Username := GlpiUser;
        idHttp.Request.Password := GlpiPassword;
        IdHTTP.Request.ContentEncoding := 'utf-8';
        IdHTTP.Request.CustomHeaders.Values['Authorization'] :=  'user_token  ' + userToken;
        IdHTTP.Request.CustomHeaders.Values['App-Token'] :=  AppToken;

        Answer := IdHTTP.Get(GlpiRestUrl + '/initSession/');
        JSON := TJSONObject.ParseJSONValue(Answer) as TJSONObject;
        Result := JSON.Get('session_token').JsonValue.Value;

      finally
        IdHTTP.Free;
      end;
    finally

    end;

  except
    on E: Exception do
      ShowMessage('Error: '+E.ToString);
  end;

end;

Также нам понадобиться функция для закрытия сессии:

Function KillSession (sToken: string) : boolean;
    var
      IdHTTP: TIdHTTP;
      Answer: string;
begin
  if sToken = '' then Exit;
  try
    try
      IdHTTP := TIdHTTP.Create(nil);
      try
        IdHTTP.Request.Connection := 'Keep-Alive';
        IdHTTP.Request.ContentType := 'application/json';
        idHttp.Request.BasicAuthentication := true;
        idHttp.Request.Username := GlpiUser;
        idHttp.Request.Password := GlpiPassword;
        IdHTTP.Request.ContentEncoding := 'utf-8';
        IdHTTP.Request.CustomHeaders.Values['Session-Token'] := sToken ;
        IdHTTP.Request.CustomHeaders.Values['App-Token'] :=  AppToken;

        Answer := IdHTTP.Get(GlpiRestUrl + '/killSession/');

        if IdHttp.ResponseCode = 200 then Result := true
                                     else Result := false;

      finally
        IdHTTP.Free;
      end;
    finally

    end;

  except
    on E: Exception do
      ShowMessage('Error: '+E.ToString);
  end;

end;

Ну и сама функция создания заявки с прикреплением файла:

Function CreateTiket (sToken : string): string;
    var
      IdHTTP: TIdHTTP;
      Answer: string;
      JSON, JSON2, JSON3 : TJSONObject;
      JsonToSend: TMemoryStream;
      jsontext : string;
      doc_id, doc_prefix, doc_file : string;
      MultiData : TIdMultiPartFormDataStream;
      JSONArray : TJSONArray;
      newticket_id : string;
begin
  try

    try

     IdHTTP := TIdHTTP.Create(nil);
      try
        IdHTTP.Request.Connection := 'Keep-Alive';
        IdHTTP.Request.ContentType := 'multipart/form-data';     // Это для загрузки документов
        idHttp.Request.BasicAuthentication := true;
        idHttp.Request.Username := GlpiUser;
        idHttp.Request.Password := GlpiPassword;
        Idhttp.Request.AcceptEncoding := 'gzip, identity;q=0';
        IdHttp.Compressor := TIdCompressorZLib.Create(IdHttp);
        Idhttp.Request.Accept := 'application/json';
        Idhttp.HTTPOptions := [hoKeepOrigProtocol,hoForceEncodeParams,hoNoProtocolErrorException,hoWantProtocolErrorContent];
        IdHTTP.Request.ContentEncoding := 'utf-8';
        //Параметр user_token берётся из Ключ удалённого доступа настроек пользователя Администрирование -> Пользователи -> USERNAME -> Настройки
        IdHTTP.Request.CustomHeaders.Values['Authorization'] :=  'user_token  ' + userToken;
        //"Настройки"->"Общие"->"API" и нажав кнопку "Добавить клиента", добавляем запись и генерируем токен (app_token)
        IdHTTP.Request.CustomHeaders.Values['App-Token'] :=  AppToken;
        //"Session-Token" получаем в функции
        IdHTTP.Request.CustomHeaders.Values['Session-Token'] := sToken ;

       //Старт  Загружаем файл
        MultiData := TIdMultiPartFormDataStream.Create;
        MultiData.AddFormField('uploadManifest', '{"input": {"name": "Документ заявки 0000", "_filename" : "DocName", "is_recursive" : true}}', 'utf-8', 'application/json').ContentTransfer := '8bit';
        with MultiData.AddFile('filename[0]','c:\testpicture01.jpg','') do //добавляем файл
          begin
                    HeaderCharset := 'utf-8';
                    HeaderEncoding := '8';
            end;
//Конец  Загружаем файл

        //GlpiRestURL - путь к вашему GLPI. Например 'http://10.0.0.10/glpi/apirest.php';
        Answer := IdHTTP.Post(GlpiRestURL + '/Document/', MultiData);  // отправляем документ

        MultiData.Free;

        //Старт Разбираем полученный ответ
        JSON := TJSONObject.ParseJSONValue(Answer) as TJSONObject;

        doc_id := JSON.Get('id').JsonValue.Value;    // Получаем ID загруженного файла

        JSON2 := TJSONObject(JSON.Get('upload_result').JsonValue);

        JSONArray := TJSONArray(JSON2.Get(0).JsonValue);

        JSON3 := TJSONObject(JSONArray.Get(0));

        doc_file := JSON3.GetValue('name').Value; // Эти значения не нужны, это для примера разбора JSON

        doc_prefix := JSON3.GetValue('prefix').Value; //Эти значения не нужны, это для примера разбора JSON
        //Конец Разбираем полученный ответ

        if (IdHttp.ResponseCode <> 200) and (IdHttp.ResponseCode <> 201)  then Result := 'Ошибка при создании заявки (' + Answer + ')'
                                       else
         begin
             // Старт Отправляем запрос на создание заявки
             IdHTTP.Request.ContentType := 'application/json';    // Это отправки json
              jsontext := '{"input": {"name": "Заявка тестовая", "content": "Описание","status":"1",' +
                '"requesttypes_id":"8","_users_id_assign":"23","time_to_resolve":"2020-06-13 18:00:00",'+
                '"itilcategories_id":"23","urgency":"3","priority":"3"}}';
              JsonToSend := TStringStream.Create(jsontext, TEncoding.UTF8);

              Answer := IdHTTP.Post(GlpiRestURL + '/Ticket', JsonToSend);

              JSON := TJSONObject.ParseJSONValue(Answer) as TJSONObject;

              newticket_id := JSON.Get('id').JsonValue.Value;    //Получяаем ID созданной заявки
              //Конец Отправляем запрос на создание заявки

              // Старт Отправляем запрос на прикрепление файла к заявке
              jsontext := '{"input": {"documents_id" : "' + doc_id + '", "items_id" : "' + newticket_id + '", "itemtype" : "Ticket" }}';
              JsonToSend := TStringStream.Create(jsontext, TEncoding.UTF8);

              Answer := IdHTTP.Post(GlpiRestURL + '/Document_Item', JsonToSend);
              //Конец Отправляем запрос на прикрепление файла к заявке

              Result := 'Заявка создана'
         end;

      finally
        IdHTTP.Free;
      end;
    finally

    end;

  except
    on E: Exception do
      ShowMessage('Error: '+E.ToString);
  end;

end;

Используется например так:

procedure TForm1.Button1Click(Sender: TObject);
Begin
GlpiUser := 'GlpiUsername';
GlpiPassword := 'SuperPassword';
GlpiRestUrl := 'http://10.0.0.10/glpi/apirest.php';
 session_token := Get_session_token;
 ShowMessage(CreateTiket(session_token));
 KillSession(session_token);
end;

вторник, 21 апреля 2020 г.

Обновление MS EXCHANGE 2013


Обновление MS EXCHANGE 2013 
Исходные данные: 2 сервера CAS и 2 сервера MBX (DAG)
P.S. Данная схема протестирована успешно при обновлении с CU13 до CU23 

Обновление CAS серверов.
1.       Подготовка (делаем резервные копии файлов и реестра для всех серверов)
Во время установки обновления Exchange 2013 все конфигурационные файлы будут перезаписываться новыми. Если вы вносили какие-либо изменения в эти файлы, то вам нужно позаботиться о том, чтобы сохранить где-либо изменения, которые вы вносили.
Ниже представлен список файлов, изменения в которых необходимо сохранить куда-либо, чтобы после установки обновления их внести заново:
- IIS: файлы web.config MBX роли (они располагаются в подпапках по пути C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess) – их изменение обычно связано, например, с интеграцией с Lync или с исправлением, когда учетная запись имеет слишком большое членство в группах
- IIS: файлы web.config CAS роли (они располагаются в подпапках по пути C:\Program Files\Microsoft\Exchange Server\V15\FrontEnd\HttpProxy) – их изменение обычно связано, например, с исправлением, когда учетная запись имеет слишком большое членство в группах
- Exchange: файлы *.config – конфигурационные файлы служб Exchange (они располагаются по пути C:\Program Files\Microsoft\Exchange Server\V15\Bin) – их изменение обычно связано, например, с необходимостью увеличить количество одновременных перемещений почтовых ящиков
- Exchange: реестр (расположение HKLM\Software\Microsoft\ExchangeServer\V15)

2.       Выводим обновляемый сервер из балансировки
Запускаем Панель управления\Все элементы панели управления\Администрирование\ «Диспетчер балансировки сетевой нагрузки»
На обновляемом сервере нажимаем ПКМ – Узел управления – Стоп.
Далее опять на обновляемом сервере нажимаем ПКМ – Свойства узла – Состояние по умолчание выбираем «Остановлена». Применить.

3.       Переводим сервер в режим обслуживания
В Exchange Management Shell (EMS) выполняем команду:
Set-ServerComponentState CAS02 -Component ServerWideOffline -State inactive -Requester Maintenance

4.       При необходимости устанавливаем Framework требуемой версии и Visual C++ Redistributable
- Устанавливаем Visual C++ Redistributable
- Устанавливаем Framework
- Перезагружаемся

5.       Подготавливаем Active Directory (это делается один раз на первом сервере)
Теперь перейдем в директорию с распакованным обновлением (CU) и расширим схему AD (нужен компонент Windows Server "RSAT-ADDS" и обновление безопасности) будем использовать для этого cdm.exe запущенную от Администратора:
setup.exe /prepareschema /IAcceptExchangeServerLicenseTerms
Подготовим Active Directory:
setup.exe /preparead /IAcceptExchangeServerLicenseTerms
Подготовим домен (запускается для каждого домена, содержащего почтовый сервер Exchange):
setup.exe /PrepareDomain /IAcceptExchangeServerLicenseTerms


6.       Устанавливаем обновление
- Запускаем cmd.exe.
- Переходим в папку с распакованным обновлением и запускаем обновление командой:
setup /m:Upgrade /IAcceptExchangeServerLicenseTerms
- Перезагружаем сервер.

7.        Выводим сервер из режима обслуживания
В Exchange Management Shell (EMS) выполняем команду:
Set-ServerComponentState CAS02 -Component ServerWideOffline -State active -Requester Maintenance

8.       Возвращаем сервер в балансировку
Далее опять на обновляемом сервере нажимаем ПКМ – Свойства узла – Состояние по умолчание выбираем «Работает». Применить.
На обновляемом сервере нажимаем ПКМ – Узел управления – Старт.

9.       Проверяем работоспособность
Get-ServerComponentState Name_Of_CAS_server

10.   Для других CAS серверов  все то же самое, только пропускаем пункт 1, 5


Обновление MBX серверов в DAG.

1.       Переводим сервер в режим обслуживания
В Exchange Management Shell (EMS) выполняем команды:
Set-ServerComponentState mbx01 -Component HubTransport -State Draining -Requester Maintenance

Redirect-Message -Server mbx01 -Target mbx02

Suspend-ClusterNode mbx01

Set-MailboxServer mbx01 -DatabaseCopyActivationDisabledAndMoveNow $True

Set-MailboxServer mbx01 -DatabaseCopyAutoActivationPolicy Blocked

Set-ServerComponentState mbx01 -Component ServerWideOffline -State Inactive -Requester Maintenance

2.       При необходимости устанавливаем Framework требуемой версии и Visual C++ Redistributable
- Устанавливаем Visual C++ Redistributable
- Устанавливаем Framework
- Перезагружаемся

3.       Устанавливаем обновление
- Запускаем cmd.exe.
- Переходим в папку с распакованным обновлением и запускаем обновление командой:
setup /m:Upgrade /IAcceptExchangeServerLicenseTerms
- Перезагружаем сервер.

4.        Выводим сервер из режима обслуживания
В Exchange Management Shell (EMS) выполняем команды:
Set-ServerComponentState mbx01 -Component ServerWideOffline -State Active -Requester Maintenance

Resume-ClusterNode mbx01

Set-MailboxServer mbx01 -DatabaseCopyActivationDisabledAndMoveNow $False

Set-MailboxServer mbx01 -DatabaseCopyAutoActivationPolicy Unrestricted

Set-ServerComponentState mbx01 -Component HubTransport -State Active -Requester Maintenance

5.       Проверяем работоспособность
В Exchange Management Shell (EMS) выполняем команды:
Get-ExchangeServer | ft Name, ServerRole, AdminDisplayVersion –AutoSize

Get-ClusterNode

Test-ServiceHealth

Test-MAPIConnectivity -Database maildb1 для каждой базы

Get-MailboxDatabase | Get-MailboxDatabaseCopyStatus | ft Name, Status, CopyQueueLength, ReplayQueueLength, ContentIndexState –AutoSize

Test-ReplicationHealth -Server mbx01

Get-MailboxServer | ft name, *activ*

Get-ServerComponentState mbx01

6.       Для других MBX серверов  аналогично


Полезные ссылки









понедельник, 11 сентября 2017 г.

Долго не выкладывал обновления программы Helpdesk FindUser. Сейчас готова версия 2.4.0 Описывать все изменения не буду, лучше опишу возможности текущей версии программы.



1. Программа осуществляет поиск компьютера, за которым работает пользователь, по выводимому имени, логину, ip адресу, имени компьютера,  операционной системе, подключенному принтеру. Также поиск может осуществляться только по Active Directory.
2. Редактирование данных пользователя Active Directory, смена пароля и типа входа, блокирование, разблокирование и удаление пользователя.
3. Быстрое подключение к удаленному компьютеру с помощью программ удаленного управления. Существует возможность привязывать любую программу удаленного доступа (Radmin, Dameware, ...)

четверг, 18 августа 2016 г.

Аудит подключений по VPN к Forefront TMG

При подключении к VPN серверу в журнале "Безопасности" пишутся события с ID 6278 и 6272. Ранее я писал как с помощью "Планировщика задач" можно эти события отловить и выполнить powershell скрипт, который отправить информацию на почтовый адрес.
Ниже текст скрипта.

среда, 17 августа 2016 г.

Перемещение почтовой базы на другой диск (Exchange 2013 Database Availability Group (DAG))

1. Проверяем, что с базами все в порядке и процесс архивирования завершен:
Get-MailboxDatabase -Status | format-table Name,Mounted,BackupInProgress, OnlineMaintenanceInProgress

2. Удаляем копию перемещаемой базы с пассивного сервера:
Remove-MailboxDatabaseCopy –Identity <Database name>\<Сервер> -Confirm:$False

3. Отключаем активную базу:
Dismount-Database –id <Database name> –Confirm:$False 

вторник, 28 июня 2016 г.

Аудит серверов с помощью скриптов на powershell и "Планировщика задач".

     Есть такая задача у администраторов, знать кто, когда и что. Так как на домен-контроллере события в Журнале Безопасности редко хранятся больше суток (уж больно много их плодится там), то решено было вести мониторинг с помощью отслеживания срабатывания на определенные "Event ID" в "Планировщике заданий" и последующей выборкой данных из журнала и отсылкой на почту с помощью powershell-скриптов.