В этой статье мы подробно рассмотрим, как эффективно запретить тестовым базам 1С подключаться к продуктивной внешней базе SQL. Эта проблема является критически важной для обеспечения целостности данных и стабильности работы производственных систем, особенно когда взаимодействие 1С с SQL-базой происходит напрямую через COM-объект, а параметры подключения хранятся внутри конфигурации 1С. Мы проанализируем различные подходы как со стороны платформы 1С, так и со стороны SQL Server, чтобы предложить комплексное и надежное решение.
Ситуация, когда тестовые базы 1С случайно или намеренно обращаются к продуктивной внешней базе SQL, возникает достаточно часто. Основная причина кроется в простоте копирования информационных баз 1С. После создания копии, все настройки подключения к внешним ресурсам, включая критичные параметры для продуктивной SQL-базы, сохраняются. Это может привести к следующим рискам:
В данной ситуации, когда переход на более современные технологии взаимодействия не рассматривается, мы должны сосредоточиться на максимально надежных механизмах запрета доступа в существующих условиях.
Для эффективного запрета мы предлагаем рассмотреть многоуровневый подход, сочетающий в себе:
Основной принцип заключается в том, чтобы 1С-база самостоятельно определяла, является ли она продуктивной рабочей базой или тестовой копией, и на основании этого блокировала или разрешала подключение к внешней SQL-базе. Мы разберем по шагам, как это можно реализовать.
Мы используем функции платформы 1С для получения уникального имени текущей информационной базы в кластере серверов 1С и имени сервера, на котором она запущена. Это позволяет нам получить уникальный идентификатор для каждой базы, что является надежным критерием для определения "рабочей" или "тестовой" копии.
// Пример получения имени текущей базы в кластере
Функция ПолучитьИмяТекущейБазы1С() Экспорт
Возврат НСтр(СтрокаСоединенияИнформационнойБазы(), "Ref");
КонецФункции
// Пример получения имени сервера 1С, если необходимо
Функция ПолучитьИмяСервера1С() Экспорт
Возврат ИмяКомпьютера(); // Возвращает имя компьютера, на котором запущен сеанс
// Для кластерного режима может потребоваться более сложная логика через COM-объекты сервера 1С
// или анализ СтрокаСоединенияИнформационнойБазы() на предмет адреса сервера.
КонецФункции
Функция СтрокаСоединенияИнформационнойБазы() возвращает строку, описывающую текущее подключение к информационной базе. С помощью функции НСтр(Строка, "Ref") мы извлекаем имя базы, зарегистрированное в кластере 1С. Это имя является достаточно стабильным идентификатором, который можно использовать для проверки.
Для того чтобы 1С-база могла отличить себя от копии, нам необходимо где-то хранить список "разрешенных" имен баз и/или серверов. Мы можем создать константу или элемент справочника, который будет содержать эти данные. Например, это может быть строка с именами рабочей базы и сервера, разделенными каким-либо символом (например, запятой или точкой с запятой). При создании копии базы эти параметры будут также скопированы, но логика проверки будет использовать их для идентификации.
// Пример константы для хранения путей рабочей базы и серверов
// Значение: "МояРабочаяБаза,Сервер1СПродуктив"
// Или более сложное: "БазаПродакшн1@СерверProd1,БазаПродакшн2@СерверProd2"
Константы.РабочиеИдентификаторыБаз.Получить();
Мы рекомендуем хранить не только имя базы, но и имя сервера 1С, так как это добавляет дополнительный уровень проверки и затрудняет обход блокировки, если база будет перенесена на другой сервер.
Создадим общий модуль (например, УправлениеВнешнимиПодключениями) и в нем функцию, которая будет выполнять проверку текущей базы на соответствие "рабочим" параметрам. Эта функция будет возвращать Истина, если база является рабочей, и Ложь в противном случае.
Функция БазаРабочая() Экспорт
ИмяТекущейБазы = ПолучитьИмяТекущейБазы1С();
ИмяТекущегоСервера = ПолучитьИмяСервера1С(); // Или имя сервера кластера, если доступно
РабочиеИдентификаторы = Константы.РабочиеИдентификаторыБаз.Получить(); // "БазаПрод@СерверПрод"
МассивРабочихИдентификаторов = СтрРазделить(РабочиеИдентификаторы, ",", Ложь);
Для Каждого РабочийИдентификатор Из МассивРабочихИдентификаторов Цикл
РабочийИдентификатор = СокрЛП(РабочийИдентификатор);
Если СтрДлина(РабочийИдентификатор) = 0 Тогда Продолжить; КонецЕсли;
МассивЧастей = СтрРазделить(РабочийИдентификатор, "@", Ложь);
Если МассивЧастей.Количество() <> 2 Тогда Продолжить; КонецЕсли;
ИмяРазрешеннойБазы = СокрЛП(МассивЧастей[0]);
ИмяРазрешенногоСервера = СокрЛП(МассивЧастей[1]);
Если СтрСравнить(ИмяТекущейБазы, ИмяРазрешеннойБазы, Ложь) = 0 И
СтрСравнить(ИмяТекущегоСервера, ИмяРазрешенногоСервера, Ложь) = 0 Тогда
Возврат Истина; // Текущая база совпадает с одной из разрешенных
КонецЕсли;
КонецЦикла;
Возврат Ложь; // База не является рабочей
КонецФункции
Мы используем СтрРазделить() и СтрСравнить() для парсинга и сравнения. Важно учесть регистр символов при сравнении, но в данном случае Ложь в третьем параметре СтрСравнить() делает сравнение без учета регистра, что часто является более гибким подходом.
Найдем все места в коде 1С, где происходит подключение к внешней SQL-базе через COM-объект. Если подключение централизовано в одной или нескольких процедурах/функциях (что крайне рекомендуется для удобства поддержки), то это значительно упрощает задачу. Перед каждым вызовом метода, который устанавливает соединение или выполняет операции с внешней базой, мы добавляем проверку:
Процедура ПодключитьсяКВнешнейБазеSQL() Экспорт
Если НЕ БазаРабочая() Тогда
Сообщить("ВНИМАНИЕ! Текущая база не является продуктивной. Подключение к внешней SQL-базе заблокировано.");
ВызватьИсключение "Попытка подключения тестовой базы к продуктивной SQL-базе.";
// Или просто Возврат; в зависимости от требуемого поведения
Возврат;
КонецЕсли;
Попытка
// Здесь основной код создания COM-объекта и подключения к внешней базе SQL
// COMОбъект = Новый COMОбъект("ADODB.Connection");
// COMОбъект.ConnectionString = "Provider=SQLOLEDB.1;Data Source=...";
// COMОбъект.Open();
// ... дальнейшие операции чтения/записи
Сообщить("Успешное подключение к внешней SQL-базе.");
Исключение
Сообщить("Ошибка при подключении или работе с внешней SQL-базой: " + ОписаниеОшибки());
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
Мы предлагаем либо выводить сообщение и возвращаться, либо вызывать исключение, чтобы явно прервать выполнение операции. Вызов исключения может быть предпочтительнее, если есть необходимость остановить всю цепочку вызовов, которая могла бы привести к нежелательным действиям.
Если в вашей конфигурации используется Библиотека стандартных подсистем (БСП), то вы можете проверить наличие функциональности запрета на доступ к внешним ресурсам. БСП часто имеет механизмы для определения "копий" базы или для управления регламентными заданиями, которые можно адаптировать для ваших целей. Например, в БСП есть флаг для блокировки регламентных заданий в копиях, и можно расширить эту логику на другие внешние подключения.
Важно отметить, что помимо кнопок, регламентные задания также могут инициировать подключения к внешней SQL-базе. Для регламентных заданий в копиях баз обычно устанавливают флаг блокировки. Однако это не всегда гарантирует отсутствие проблем, особенно если флаг забыли установить или если пользователи инициируют действия вручную. Тем не менее, это хороший дополнительный слой защиты.
В коде, выполняющем регламентные задания, также следует использовать нашу функцию БазаРабочая(). Кроме того, в БСП или аналогичных решениях часто используется параметр сеанса, который может блокировать работу с внешними ресурсами.
Если ПараметрыСеанса.РаботаСВнешнимиРесурсамиЗаблокирована Тогда
Сообщить("Доступ к внешним ресурсам заблокирован в текущем сеансе.");
Возврат;
КонецЕсли;
// Далее основной код регламентного задания или другой операции с внешними ресурсами
Мы также можем адаптировать механизмы, используемые 1С для определения перемещения базы или для управления обновлениями (например, с помощью параметра запуска ЗапуститьОбновлениеИнформационнойБазы), чтобы добавить дополнительные проверки на статус "копии".
Для более гибкого управления подключением, особенно в средах разработки, мы можем использовать переменные окружения операционной системы или внешние конфигурационные файлы (например, XML, INI) на сервере 1С. Мы можем хранить параметры подключения к внешней SQL-базе не в константах 1С, а в этих внешних источниках.
Этот подход позволяет управлять подключением без модификации кода 1С при ее копировании, так как настройки считываются из окружения сервера, а не из самой базы.
Не менее важным аспектом является настройка самой СУБД SQL Server для обеспечения безопасности. Эти меры дополняют программные блокировки в 1С и обеспечивают дополнительный уровень защиты, который работает независимо от логики 1С.
Предполагаем, что для каждой информационной базы 1С, которая подключается к внешней SQL-базе, мы используем отдельного пользователя SQL Server. Например, для продуктивной базы 1С-ПРОД мы заводим пользователя User1CPRD, а для тестовой базы 1С-ТЕСТ – пользователя User1CTST. Затем мы выдаем этим пользователям различные права:
User1CPRD получает полные права на чтение/запись в необходимые таблицы внешней базы.User1CTST получает только права на чтение, или не имеет прав вообще, или имеет права на чтение/запись в отдельную, заведомо тестовую версию внешней базы.Этот метод требует согласования с администраторами SQL-базы и разработчиками, но является очень эффективным, поскольку даже если тестовая база 1С попытается подключиться, она получит либо отказ в доступе, либо ограниченные права.
Триггеры входа позволяют нам перехватывать попытки подключения к SQL Server на уровне сервера. Внутри триггера мы можем проверять различные свойства подключения и, при определенных условиях, отклонять его.
Мы можем проверять такие параметры, как:
APP_NAME(): Имя клиентского приложения (может быть "1CV8" или другое, в зависимости от настроек подключения).HOST_NAME(): Имя компьютера, с которого происходит подключение (имя сервера 1С).CLIENT_NET_ADDRESS(): IP-адрес клиента.Если эти параметры соответствуют известным тестовым базам 1С или серверам 1С, мы можем отклонить вход. Это мощный инструмент централизованного управления доступом, который не требует изменений в коде 1С.
-- Пример запроса для получения информации о текущем подключении
SELECT APP_NAME() AS ApplicationName,
HOST_NAME() AS HostName,
CLIENT_NET_ADDRESS() AS ClientIP;
-- Пример создания Logon Trigger (представление логики, а не полный код)
CREATE TRIGGER BlockTest1CLogon
ON ALL SERVER FOR LOGON
AS
BEGIN
DECLARE @appName NVARCHAR(128) = APP_NAME();
DECLARE @hostName NVARCHAR(128) = HOST_NAME();
DECLARE @clientIP NVARCHAR(48) = CLIENT_NET_ADDRESS();
DECLARE @loginName NVARCHAR(128) = ORIGINAL_LOGIN();
-- Определяем список "черных" идентификаторов
IF @loginName IN ('User1CTST') AND @hostName IN ('TestServer1C', 'DevServer1C') THEN
ROLLBACK; -- Отклоняем попытку входа
ELSE IF @appName = '1CV8' AND @clientIP = '192.168.1.100' THEN -- IP тестового сервера 1С
ROLLBACK;
END IF;
END;
Если параметры подключения соответствуют критериям "тестовой" базы, триггер отклоняет вход, и 1С не сможет установить соединение.
Помимо сетевого файрвола на границе сети, сам Windows Server, где установлен SQL Server, имеет встроенный брандмауэр. Мы можем настроить его так, чтобы разрешить входящие подключения к SQL Server только с определенных IP-адресов серверов 1С (продуктивных) и запретить со всех остальных (тестовых). Это обеспечивает дополнительный, низкоуровневый контроль доступа на уровне операционной системы.
Мы можем разрешить подключения только с определенных IP-адресов или диапазонов, блокируя доступ для всех остальных. Это является эффективным средством, если тестовые и продуктивные среды находятся на разных серверах с разными IP-адресами.
Вместо использования прямых логинов SQL Server, 1С может подключаться под определенной "ролью приложения" SQL Server. Эта роль активируется с помощью пароля, который передается при подключении. Мы можем создать две роли приложений:
AppRole_Prod с полными правами на внешнюю базу.AppRole_Test с ограниченными правами или без прав на продуктивные данные.Разграничение прав доступа между тестовыми и продуктивными базами будет реализовано путем предоставления тестовым базам доступа к AppRole_Test, а продуктивным — к AppRole_Prod. Таким образом, даже если тестовая база "узнает" логин, она все равно не сможет получить доступ к данным без активации соответствующей роли приложения с правильным паролем, который будет храниться в защищенном месте и различаться для продуктивной и тестовой сред.
Наиболее фундаментальный подход к предотвращению нежелательных подключений — это строгое физическое или логическое разделение тестовой и продуктивной сред. Мы должны стремиться к полной изоляции:
Это не только минимизирует риски случайного воздействия, но и повышает общую безопасность ИТ-инфраструктуры, делая невозможным прямое подключение тестовых компонентов к продуктивным.
Мы рассмотрели разнообразные подходы к решению задачи запрета тестовой базе 1С подключаться к внешней SQL-базе. Оптимальное решение обычно включает комбинацию программных доработок на стороне 1С (идентификация базы, централизованная проверка подключения), настроек безопасности на стороне SQL Server (разделение пользователей, триггеры входа, брандмауэр, роли приложений) и строгих организационных мер по разделению сред. В условиях, когда прямой COM-доступ является неизбежностью, многоуровневая защита становится критически важной. Применяя эти методы, мы сможем значительно снизить риск нежелательных операций и обеспечить стабильность продуктивной системы.