gifts2017

Отражение атаки клонов

Опубликовал Александр (kg_am) в раздел Программирование - Практика программирования

О том, как всего один реквизит в справочнике и несколько строк кода могут навсегда избавить нас от совершенно инфернальной жути.

Проблема

Допустим, сделали интеграцию системы А с системой Б. Всё хорошо, системы работют, данные ходят:

Нормальный обмен между системами


Вдруг случается «неожиданность». Систему Б скопировали. Образовалась система Б`, в которой пользователи тестируют новую функциональность, обучаются и т.п. Когда наступает час «икс», система Б` вступает в информационный обмен с системой А:

Появился клон

Возникают «маленькие неудобства»:

  1. Система А думает, что она успешно передала в систему Б данные, но в системе Б данные не появились потому что были перехвачены системой Б`.
  2. Система А получает странного вида мусор («игрушечные» данные), которые пользователь ввёл в Б`.

Основная идея «Антиклона»

Для того, чтобы решить проблему клонов, нужно сделать так, чтобы система (например, система Б`) при необходимости могла сама определить, является она оригиналом или его клоном. Основной вопрос: «Чем клон отличается от оригинала?» Ответ: расположением.

Расположение информационной базы легко определяется функцией СтрокаСоединенияИнформационнойБазы()

Решение №1, самое простое

Добавляем константу строкового типа, в которую администратор вводит строку соединения с информационной базой. В примере ниже эта константа названа Антиклон_СтрокаСоединенияИнформационнойБазы.

При начале '''каждой''' попытки вступить в информационный обмен делаем такую простую проверку:

Если ВРег(СокрЛП(Константы.Антиклон_СтрокаСоединенияИнформационнойБазы.Получить()))
        <> ВРег(СтрокаСоединенияИнформационнойБазы()) Тогда
    ВызватьИсключение "Запуск обмена из клона информационной базы";
КонецЕсли;

Примечание: вызов исключения вписан для примера. В реальных системах обычно идёт запись сообщения в протокол обмена и возврат со статусом «Обмен не выполнен».

Недостатки решения №1

Что будет, если нужно создать тестовую площадку (клон системы А, общающийся с клоном системы Б)? Но при этом не общающийся с системой В?

Скорее всего, часть информационных обменов администратор, разворачивающий тестовую площадку, отключит, часть - перенаправит, но про что-то он вполне может забыть:

Проблема вернулась

Проблему с клонами уже не ждали, но она вернулась.

Решение №2

  1. Допустим, у нас есть некий справочник, в котором параметризуется обмен (указывается каталог обмена или адрес FTP, настраивается расписание и т.п.). Строку соединения с инф. базой делаем реквизитом этого справочника.
  2. Этот реквизит автоматически инициализируем при создании нового элемента.
  3. На формах показываем, но менять не даём. Если нужно, пусть администратор создаёт новую настройку.
  4. Контроль в коде – аналогично решению №1 (всё равно обмен всегда параметризуется настройкой).

Обмены бывают разные, параметризуются они разными способами. Может возникнуть неоднозначность - куда пристроить сохраняемый параметр СтрокаСоединенияСБазой? Правило простое: туда же, где задаются параметры канала связи. Если обмен файловый и путь сохранения («почтовый ящик») устанавливается в константе, то и антиклон задаётся в константе. Если обмен через веб-сервис, параметры (URL, имя сервиса и др.) которого задаются в реквизитах узла плана обмена, то и СтрокаСоединенияСБазой становится реквизитом узла плана обмена. И так далее.

Недостатки решения №2

  1. Дополнительное действие по перенастройке при переносе рабочей базы (скопировать используемые настройки, перевыбрать их в качестве основных используемых, заново настроить расписания).
  2. Ситуация: базу перенесли на новое место, а старое забыли заблокировать (уничтожить). Обе базы – «ну как живые». Проблема с клонами в полном объёме.

Решение №3, параноидальное

Защищаемся с двух сторон: не только Б` отказывается вступать в обмен со старыми настройками, но и А опознаёт, что пакет пришёл от клона.

В дополнение к решению №2:

  1. В настройки обмена (или в узел плана обмена) добавляется реквизит СтрокаСоединенияУзла, куда в базе А вписывается идентификация Б, а в базе Б вписывается идентификация А.
  2. В пакет обмена добавляется передача строки соединения передающей стороны.
  3. При приёме пакета: если СтрокаСоединенияУзла пустая, она заполняется тем, что указано в пакете обмена, если не пустая – контролируется совпадение.

Важно: реквизит СтрокаСоединенияУзла нужно сделать доступным для редактирования администратором.

Недостаток решения №3

При переносе рабочей базы нужно поменять не только её настройки, но и настройки во всех базах, которые с ней общаются.

Маленькое, но важное дополнение

Проблема клонов возникает не только если есть общающиеся между собой системы. Даже если система одна, в ней внутри может возникнуть проблема клонов.

История такая. В одной из наших систем нужно было сделать возможность прикрепления файлов к объектам системы. Сканы договоров и актов, счетов-фактур и т.п. Поскольку система большая и документов много, хранить это всё внутри базы посчитали не целесообразным (в том числе потому, что не хочется ездить за копией базы с терабайтным хардом). Сделали так, чтобы прикреплённые файлы хранились отдельно от базы - в специальном каталоге. А в базе хранится ссылка на файл.

По сути, массив данных системы перестал представлять собой единое целое, и появилась возможность отклонировать одну его часть так, что вторая часть при этом стала в общем пользовании и у оригинала, и у копии. Конечно же, оно случилось.

В какой-то момент на том же сервере, где жила рабочая база, завелась ещё и тестовая база. В тестовой базе пользователи тоже вовсю поигрались с прикреплением файликов к документам системы. Результат: человек открывает скан договора, а ему вместо нужного скана - что-то совсем левое. Просто потому, что файл, прикреплённые пользователем тестовой базы, тоже сел на этот же номерок.

Нам повезло, что проблема обнаружилась почти сразу и объём потерянных данных оказался небольшим. Быстренько прикрутили внутрисистемный антиклон, и тестовая база (а также автоматически все остальные тестовые базы, которые потом неоднократно появлялись) была отлучена от файлового хранилища рабочей базы. Если бы проблема была обнаружена через полгода, нас, наверно, убили бы.

Когда антиклон не нужен?

Если система А общается с системой Б, подключаясь к ней напрямую (например, через COM-соединение или через веб-сервис), в системе Б антиклон не нужен.

Но в системе А нужен!!!

Мораль

Прикрутил обмен - НЕ ЗАБУДЬ ПРИКРУТИТЬ АНТИКЛОН. Хотябы какой-нибудь, но лучше параноидальный.

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Михаил Афанасьев (mikmike) 28.10.13 06:24
Статья из серии необходимости резервного копирования. Вроде бы все и так понятно, но ... постоянно кто-то да на грабли наступит.
Спасибо за напоминание и некую формализацию решения.
2. Александр (kg_am) 28.10.13 11:23
(1) Совершенно верно. Разница лишь в том, что про необходимость резервного копирования нам с детства все уши прожужжали, а проблемы, появляющиеся в результате обменов с клонами, каждый раз становятся сюрпризом.
3. Андрей Акулов (DrAku1a) 31.10.13 07:39
Я для себя решил проблему просто - создал константу со списком путей всех ИБ (список значений, хотя можно и строку через запятую), смотрим - если база числится в списке, то она считается рабочей базой - нет, тогда копией. Обмены с копией запрещаем. И еще сделал программно модификацию заголовка при запуске (см. изображение). Код не сложный, но могу продемонстрировать...
Прикрепленные файлы:
Светлый ум; +1 Ответить 1
4. Александр (kg_am) 31.10.13 12:50
(3) То есть ищем себя в списке рабочих баз, и если не находим, то мы - клон?
А почему список, а не просто строка? Для того, чтобы иметь возможность работать при разных вариантах строк соединения? Например, и при такой: "Srvr="server1";Ref="buh";", и при такой: "Srvr="123.45.67.8";Ref="buh";"?
Или во все имеющиеся базы зафигачиваем список всех рабочих баз, которые есть?

Кстати, за подсказку по вариативности строки соединения спасибо. Надо над этим подумать. Периодически такая проблема возникает, особенно в файловом варианте, и мы просим админов при подключении пользователей вводить абсолютный сетевой путь.
5. Андрей Акулов (DrAku1a) 31.10.13 13:17
(4) kg_am, На самом деле, я не использовал имя сервера (именно из-за вариативности этого имени). Все имена в списке всегда были переведены в нижний регистр - потому модно было искать имя базы при помощи функции "НайтиПоЗгачению()", но список был сделан наверное только для удобства восприятия. Можно и в строку через запятую перечислить.
Кстати, работая со строками я использую небольшую фичу:
Если Найти(","+Имя+",", ","+СписокБаз+",")>0 Тогда
...
Почему так? Да потому что може быть, например так: в списке база с именем "mybase1", а ее копию поместили в "base1".
тогда
Найти(",base,", ",mybase1,")
вернет 0, а вот
Найти("base", "mybase1")
вернет как раз >0, а именно, 3.
6. Александр (kg_am) 31.10.13 14:18
(5) Я тоже пользую этот приём, но вместо "," обычно "/", но это не важно. Только, конечно, не
Если Найти(","+Имя+",", ","+СписокБаз+",")>0 Тогда
а
Если Найти(","+СписокБаз+",", ","+Имя+",")>0 Тогда

С именем базы без имени сервера может быть засада, когда база разворачивается на тестовом сервере (или на компьютере разработчика), и ей даётся то же имя, что и у рабочей. Можно сто раз всех предупредить, что так делать нельзя, но через 15 минут все всё равно забудут. Потому что не очевидно.

И всё же. В какой момент анализируется константа? Если посмотреть на второй рисунок в статье (тот, где появился красненький квадратик "Б`"), то Ваш механизм блокирует работу обмена в Б` или же при получении пакета в базе А выясняет, что пакет пришёл от того, от кого не ждали?

Если первое, то зачем в константе нужен список всех остальных рабочих баз?
7. Андрей Акулов (DrAku1a) 31.10.13 14:44
(6) Во всех процедурах отвечающих за начало обмена данными вставил "заглушки", которые делают "Возврат", если база - копия. Т.е. обмены вообще не происходят. Так что тут вы правы, блокируем всё. На то она и копия ))

Ситуации как на втором рисунке еще не было в практике. Но возможно что-то подобное очень скоро придется реализовывать (скорее всего, будем блокировать только если обмен делается фоновым заданием, а не пользователем а обмены которые необходимо - прогонять вручную).
8. Александр (kg_am) 31.10.13 15:03
(7) Ну, то есть, применено то, что у меня описано как "решение 1", но с той разницей, что в константу запихивается список всех рабочих баз, и база ищет себя в списке достойнейших.

Вторая картинка (та, где появляется база "В") - это у нас довольно частое дело. У нас, например, есть система, которая синтегрирована и с бухгалтерией, и с зарплатой, и с самописным биллингом, и с документооборотом, и на очереди ещё есть немножко интересных задумок. Когда что-то допиливается, для тестирования приходится сдруживать клонов. Применение "решения 2" автоматически избавляет от головняка, и при этом даёт нужную гибкость в плане тестирования. Если обходиться одной константой, хранящей список достойнейших, как избежать проблем от того, что клона тоже придётся занести в список? Только заранее у клонов всё перенастроить, и ничего при этом не забыть.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа