Управление доступом и идентификация на платформе HI
COURSE-16-M04-L03 — Управление доступом и идентификация на платформе HI
Цели урока
По завершении этого урока инженер сможет:
- Объяснить принципы управления доступом и их применение в системах автоматизации на базе контроллера HI.
- Спроектировать и реализовать базовую систему контроля доступа (СКУД) с использованием RFID-считывателя и релейного выхода.
- Создать и настроить базу данных MySQL на контроллере для хранения информации о пользователях, их ролях и правах.
- Разработать поток Node-RED, реализующий логику аутентификации и авторизации на основе ролей (RBAC).
- Применять лучшие практики безопасности для защиты систем управления доступом, включая журналирование и обработку ошибок.
Введение в управление доступом и идентификацию
В контексте платформы HI, управление доступом — это не абстрактная теория, а конкретный инженерный механизм, отвечающий на вопрос: «Кто, когда и к чему может получить доступ?». Например:
- Может ли гость отеля включить свет только в своем номере или во всем коридоре?
- Имеет ли сотрудник право изменять уставку температуры в серверной или только просматривать ее?
- Может ли сервисный инженер разблокировать все двери в офисном центре или только те, что указаны в его наряд-заказе?
Принципы управления доступом на платформе HI
При проектировании систем на контроллерах HI необходимо строго следовать трем фундаментальным принципам безопасности.
- Принцип минимальных привилегий: Каждый пользователь, роль или устройство должны иметь доступ только к тем ресурсам, которые абсолютно необходимы для выполнения их задач.
- Принцип необходимости знания: Доступ к данным предоставляется только тогда, когда это необходимо.
- Контроль доступа на основе ролей (RBAC): Это наиболее эффективная модель для управления доступом в 99% проектов. Вместо назначения прав каждому индивидуальному пользователю, мы создаем роли (например, `admin`, `resident`, `guest`, `service`), назначаем права этим ролям, а затем присваиваем роли пользователям. Это кардинально упрощает администрирование.
Практическая реализация: СКУД для одной двери на контроллере HI
Рассмотрим создание простой, но надежной системы контроля доступа для одной двери на базе нашего контроллера.
Компоненты системы:Шаг 1: Проектирование базы данных
Нам понадобятся две таблицы: `users` для хранения информации о картах и ролях, и `access_log` для аудита.
Таблица `users`:CREATE TABLE `users` (
`id` INT NOT NULL AUTO_INCREMENT,
`card_uid` VARCHAR(20) NOT NULL UNIQUE,
`user_name` VARCHAR(100) NOT NULL,
`role` ENUM('admin', 'user', 'guest') NOT NULL DEFAULT 'guest',
`is_active` BOOLEAN NOT NULL DEFAULT TRUE,
PRIMARY KEY (`id`)
);
Таблица `access_log`:
CREATE TABLE `access_log` (
`id` INT NOT NULL AUTO_INCREMENT,
`ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`card_uid` VARCHAR(20) NOT NULL,
`user_name` VARCHAR(100),
`action` ENUM('grant', 'deny'),
`reason` VARCHAR(255),
PRIMARY KEY (`id`)
);
💡 Совет: Добавьте несколько тестовых пользователей с разными ролями, чтобы проверить логику.
`INSERT INTO users (card_uid, user_name, role) VALUES ('12345678', 'Admin Ivan', 'admin');`
`INSERT INTO users (card_uid, user_name, role) VALUES ('87654321', 'User Petr', 'user');`
Шаг 2: Схема подключения (WIRING-DOOR-001)
//========= WIRING-DOOR-001: Office Main Door Control =========
// USB RFID Reader (HID Emulation)
(RFID-Reader:USB) --- (USB Port) --- [CTRL:HI-Core]
// Relay Output for Electromagnetic Lock
[PSU:12VDC] [CTRL:HI-Core]
+12V --(+)------------------------------ +V
GND --(-)---+
|
L --- ~L~ ---+-- C (RL-10)
\-- NO (RL-10) --- ~L~ --- L (PSU)
N --- ~N~ ----------------------------- N (PSU)
// Примечание: Замок "нормально-закрытый" (NC). Чтобы его открыть,
// нужно подать питание. В схеме используется реле в режиме NO.
// Логика: реле выключено -> замок обесточен -> дверь открыта.
// реле включено -> замок под напряжением -> дверь закрыта.
// Для "нормально-открытых" замков используется клемма NC реле.
Шаг 3: Поток в Node-RED (FLOW-SECURITY-DOOR-001)
Этот поток реализует всю логику: чтение карты, проверка в БД, принятие решения и журналирование.
ASCII-схема потока:// Поток обработки UID карты
[node-red-contrib-usbhid] --(UID)--> [Function: Prepare SQL] --> [MySQL DB] --+
|
// Ветвление логики по результату из БД |
+--> [Switch: User Found?] --+-- (Found) --> [Function: Authorize] --> [Switch: Role?] --+
| |
+-- (Not Found) -> [Function: Log Deny] -> [Link Out: To Logger]
|
// Ветвление по ролям |
+-- ('admin'/'user') -> [Function: Grant Access] -> [rpi gpio out: RL-10] -> [Delay 5s] -> [rpi gpio out: RL-10] -> [Link Out: To Logger]
|
+-- ('guest') -> [Function: Log Deny (Guest)] -> [Link Out: To Logger]
// Централизованный поток журналирования
[Link In: From Logger] --> [Function: Prepare Log SQL] --> [MySQL DB: access_log]
// Обработка ошибок
[Catch: All Nodes] --> [Function: Format Error] --> [Debug]
Контракты сообщений:
// msg.payload приходит из узла MySQL в виде массива.
// Если пользователь найден, массив содержит один объект.
const user = msg.payload[0];
// Сохраняем информацию о пользователе в объекте msg для дальнейшего использования
msg.user = {
name: user.user_name,
role: user.role,
card_uid: user.card_uid
};
// Обновляем статус узла для визуальной диагностики
node.status({ fill: "blue", shape: "dot", text: `Auth: ${user.user_name} (${user.role})` });
return msg;
Код для узла `Function: Grant Access`:
// Этот узел получает msg с установленным msg.user
const user = msg.user;
// 1. Формируем сообщение для журналирования
msg.log_data = {
card_uid: user.card_uid,
user_name: user.name,
action: 'grant',
reason: `Access granted for role: ${user.role}`
};
// 2. Формируем команду для реле (открыть замок)
// Предполагаем, что 0 = открыть (обесточить), 1 = закрыть (подать питание)
// Это зависит от типа замка (NC/NO) и схемы подключения.
// В нашей схеме 0 открывает.
msg.payload = 0;
// Обновляем статус
node.status({ fill: "green", shape: "dot", text: `Granted: ${user.name}` });
// Отправляем сообщение на реле и в логгер
// Используем два выхода в узле Function
return [msg, { payload: msg.log_data }]; // msg на реле, {payload} в логгер
⚠️ Важно: В реальной системе пароли и другие секреты никогда не должны храниться в открытом виде. Для паролей используйте хэширование (например, bcrypt). В нашем примере с RFID UID карты является идентификатором, а не секретом.
Интеграция с внешними системами идентификации
Хотя локальная БД на контроллере HI является надежным решением, в корпоративных средах часто требуется интеграция с централизованными каталогами пользователей.
- LDAP (Lightweight Directory Access Protocol): Если на объекте есть Microsoft Active Directory или другой LDAP-сервер, вы можете использовать палитру `node-red-contrib-ldap-auth` для аутентификации пользователей. Это позволяет управлять доступом централизованно, без необходимости вести отдельную базу на каждом контроллере.
- OAuth 2.0 / OpenID Connect: Эти протоколы используются для делегирования аутентификации внешним провайдерам (например, Google, Microsoft). В контексте IoT это может быть полезно для веб-интерфейсов управления. Пользователь входит через свой корпоративный аккаунт, а ваше приложение на Node-RED получает токен доступа, подтверждающий его личность и права.
- API-токены: Самый простой способ интеграции. Внешняя система (например, CRM отеля) при наступлении события (заселение гостя) отправляет на `http in` эндпоинт контроллера HI запрос с API-токеном и данными (например, `{"card_uid": "99887766", "action": "activate", "room": 101}`). Ваш поток в Node-RED проверяет токен и выполняет действие.
Защита системы управления доступом: Чек-лист
📋 При сдаче объекта убедитесь, что выполнены следующие пункты:
* Интерфейс администратора Node-RED защищен надежным паролем (`adminAuth` в `settings.js`).
* Доступ к редактору осуществляется по HTTPS (требует настройки прокси-сервера, например, Nginx).
* Неиспользуемые порты на контроллере закрыты.
---
Лабораторные работы
COURSE-16-M04-LAB05: Базовая система контроля доступа
Задача: Используя предоставленный скелет потока, реализовать СКУД для одной двери согласно описанию в уроке. Скелет потока (JSON для импорта в Node-RED):[{"id":"...","type":"tab","label":"LAB05: Basic Access Control"}, {"id":"...","type":"comment","name":"Шаг 1: Настройте подключение к MySQL","x":200,"y":100,"wires":[]}, {"id":"...","type":"comment","name":"Шаг 2: Реализуйте логику в Function-узлах","x":220,"y":250,"wires":[]}]
(Полный JSON будет предоставлен в системе обучения)
Чек-лист выполнения:
- 3 балла: Система работает, доступ предоставляется и запрещается корректно.
- 1 балл: Все попытки доступа корректно журналируются в БД.
- 1 балл: Поток использует `node.status` для отображения текущего состояния.
COURSE-16-M04-LAB06: Усложненная система с временными зонами
Задача: Модифицировать поток из LAB05, добавив ограничение по времени для роли `guest`. Усложнение:---
Квиз по модулю
COURSE-16-M04-QUIZ
a) Дискреционное управление доступом (DAC)
b) Мандатное управление доступом (MAC)
c) Контроль доступа на основе ролей (RBAC)
d) Управление доступом на основе атрибутов (ABAC)
a) В глобальном контексте Node-RED
b) В текстовом файле на SD-карте
c) В базе данных MySQL на контроллере
d) Внутри `Function` узла в виде массива
a) `Status`
b) `Link Out`
c) `Switch`
d) `Catch`
a) Система должна иметь минимальное количество пользователей.
b) Пользователь должен иметь доступ только к ресурсам, необходимым для его работы.
c) Пароли пользователей должны быть минимальной длины.
d) Следует использовать минимальное количество реле.
a) Поток остановится с ошибкой.
b) Узел `MySQL` вернет пустой массив, и `Switch` направит поток по ветке "Not Found".
c) Дверь откроется, так как нет запрещающего правила.
d) Контроллер перезагрузится.
a) Для ускорения работы системы.
b) Для хранения паролей пользователей.
c) Для аудита безопасности и анализа инцидентов.
d) Для временного хранения данных.
a) C (общий) и NO (нормально-открытый)
b) C (общий) и NC (нормально-закрытый)
c) Только к NO
d) Только к NC
a) MQTT
b) LDAP
c) OAuth 2.0
d) Modbus
a) Задержки перед записью в лог.
b) Того, чтобы дверь оставалась открытой на 5 секунд, после чего снова блокировалась.
c) Предотвращения слишком частых считываний карты.
d) Экономии электроэнергии.
a) Скорость работы MySQL.
b) Физическая безопасность контроллера и считывателя.
c) Количество ролей в системе.
d) Длина UID RFID-карты.
---
Мини-runbook: "Что делать, если..."
COURSE-16-M04-RUNBOOK-01
- Проблема: RFID-считыватель не реагирует на карту (в `Debug` нет сообщений).
2. Решение: Переподключите считыватель. Перезапустите Node-RED. Проверьте `dmesg` в консоли Linux на предмет ошибок подключения USB-устройства.
- Проблема: Карта считывается, но доступ всегда запрещен, даже для `admin`.
2. Решение: Скопируйте UID из `Debug`-сообщения от считывателя и убедитесь, что в таблице `users` в поле `card_uid` записано точно такое же значение (без пробелов, с учетом регистра).
- Проблема: Поток останавливается с ошибкой "Connection lost" от узла `MySQL`.
2. Решение: Подключитесь к консоли контроллера по SSH и выполните команду `sudo systemctl status mysql`. Если сервис неактивен, запустите его: `sudo systemctl start mysql`. Проверьте настройки подключения в узле `MySQL` (адрес `127.0.0.1`, имя пользователя, пароль).
- Проблема: Дверь открывается, но не закрывается через 5 секунд.
2. Решение: Убедитесь, что второй узел `rpi gpio out` отправляет в реле значение, соответствующее закрытому состоянию замка (в нашем примере `1`). Проверьте, что в узле `Delay` не стоит галочка "drop intermediate messages".