ГлавнаяАкадемияCOURSE-16: Основы Интернета Вещей и практическое применение → Управление доступом и идентификация на платформе HI

Управление доступом и идентификация на платформе HI

Урок 2 · COURSE-16: Основы Интернета Вещей и практическое применение · theory

COURSE-16-M04-L03 — Управление доступом и идентификация на платформе HI

Цели урока

По завершении этого урока инженер сможет:

Введение в управление доступом и идентификацию

В контексте платформы HI, управление доступом — это не абстрактная теория, а конкретный инженерный механизм, отвечающий на вопрос: «Кто, когда и к чему может получить доступ?». Например:

Идентификация — это первый шаг этого процесса: система должна определить, кто пытается совершить действие. Это может быть сотрудник, приложивший карту к считывателю, или удаленный администратор, отправляющий команду по MQTT. Аутентификация — это проверка подлинности. Система проверяет, действительно ли предъявленная карта принадлежит сотруднику, а не является копией, или действительно ли MQTT-сообщение отправлено с доверенного сервера. Авторизация — это финальный шаг: после успешной идентификации и аутентификации система решает, разрешено ли этому пользователю выполнить запрошенное действие.

Принципы управления доступом на платформе HI

При проектировании систем на контроллерах HI необходимо строго следовать трем фундаментальным принципам безопасности.

* 💡 Пример: RFID-карта уборщицы (`role: 'cleaning'`) должна давать доступ к реле освещения в общих зонах (`RL-01`...`RL-05`), но ни в коем случае не к реле, управляющему главным водяным клапаном (`RL-22`). 💡 Пример: Панель управления для жильца квартиры должна отображать температуру только в его комнатах. Данные с датчиков соседей (`telemetry/apartment-5/`) должны быть для него недоступны. Это реализуется через корректную настройку ACL (Access Control List) в MQTT-брокере.

Практическая реализация: СКУД для одной двери на контроллере HI

Рассмотрим создание простой, но надежной системы контроля доступа для одной двери на базе нашего контроллера.

Компоненты системы:
  • Контроллер HI: Ядро системы, исполняющее логику в Node-RED.
  • RFID-считыватель: Подключается к контроллеру. Для простоты возьмем USB-считыватель, эмулирующий клавиатуру (HID). Он будет отправлять UID карты как строку.
  • Электромагнитный замок: Подключается к одному из релейных выходов контроллера (например, `RL-10`).
  • База данных MySQL: Работает на самом контроллере 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` (string) = `"12345678"`
  • После `Function: Prepare SQL`: `msg.topic` = `"SELECT * FROM users WHERE card_uid = ? AND is_active = TRUE"`
  • После `MySQL DB`: `msg.payload` (array) = `[{ id: 1, card_uid: '12345678', user_name: 'Admin Ivan', role: 'admin', is_active: 1 }]` или `[]` (пустой массив, если не найдено).
  • После `Function: Authorize`: `msg.user` (object) = `{ name: 'Admin Ivan', role: 'admin' }`
  • В потоке журналирования: `msg.log_data` (object) = `{ card_uid: '12345678', user_name: 'Admin Ivan', action: 'grant', reason: 'Role admin' }`
  • Код для узла `Function: Authorize`:
    // 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 является надежным решением, в корпоративных средах часто требуется интеграция с централизованными каталогами пользователей.

    Защита системы управления доступом: Чек-лист

    📋 При сдаче объекта убедитесь, что выполнены следующие пункты:

  • [ ] Физическая безопасность: Контроллер HI и коммутационное оборудование находятся в запертом щите.
  • [ ] Сетевая безопасность:
  • * Интерфейс администратора Node-RED защищен надежным паролем (`adminAuth` в `settings.js`).

    * Доступ к редактору осуществляется по HTTPS (требует настройки прокси-сервера, например, Nginx).

    * Неиспользуемые порты на контроллере закрыты.

  • [ ] Журналирование: Все попытки доступа (успешные и неудачные) записываются в `access_log` в MySQL с временной меткой.
  • [ ] Обработка ошибок: Поток Node-RED корректно обрабатывает ситуации, когда БД недоступна или RFID-считыватель отключен (используйте узлы `Catch` и `Status`).
  • [ ] Принцип минимальных привилегий: Роли в БД настроены, и права доступа для каждой роли проверены.
  • [ ] Регулярный аудит: Настроен механизм (например, еженедельный отчет по email), который информирует администратора о всех неудачных попытках доступа и об использовании карт с ролью `admin`.
  • ---

    Лабораторные работы

    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 будет предоставлен в системе обучения) Чек-лист выполнения:
  • [ ] Созданы таблицы `users` и `access_log` в MySQL на контроллере.
  • [ ] В таблицу `users` добавлены как минимум 2 пользователя с ролями `user` и `admin`.
  • [ ] Настроен узел `mysql` для подключения к локальной БД.
  • [ ] Заполнен код в узле `Function: Prepare SQL`.
  • [ ] Заполнен код в узле `Function: Authorize`.
  • [ ] Заполнен код в узлах `Function: Grant Access` и `Function: Log Deny`.
  • [ ] Проверена работа системы: карта `admin` открывает дверь, карта `guest` (несуществующая) не открывает.
  • [ ] В таблице `access_log` появляются записи о каждой попытке доступа.
  • Рубрика оценивания:

    COURSE-16-M04-LAB06: Усложненная система с временными зонами

    Задача: Модифицировать поток из LAB05, добавив ограничение по времени для роли `guest`. Усложнение:
  • Добавьте в таблицу `users` поля `access_start_time` (TIME) и `access_end_time` (TIME).
  • Для пользователя с ролью `guest` установите временной диапазон, например, с 09:00 до 18:00.
  • Измените SQL-запрос и логику в Node-RED так, чтобы доступ для роли `guest` предоставлялся только в указанное время. В остальное время доступ должен быть запрещен с причиной "Time restriction".
  • Чек-лист выполнения:
  • [ ] Структура таблицы `users` изменена.
  • [ ] SQL-запрос в Node-RED учитывает текущее время.
  • [ ] Проверена работа: карта `guest` работает в разрешенный интервал и не работает вне его.
  • [ ] В `access_log` записывается корректная причина отказа ("Time restriction").
  • ---

    Квиз по модулю

    COURSE-16-M04-QUIZ

  • Что является основной моделью управления доступом, рекомендуемой для платформы HI?
  • a) Дискреционное управление доступом (DAC)

    b) Мандатное управление доступом (MAC)

    c) Контроль доступа на основе ролей (RBAC)

    d) Управление доступом на основе атрибутов (ABAC)

  • Где должны храниться данные о пользователях и их правах в типовом проекте на контроллере HI?
  • a) В глобальном контексте Node-RED

    b) В текстовом файле на SD-карте

    c) В базе данных MySQL на контроллере

    d) Внутри `Function` узла в виде массива

  • Какой узел Node-RED используется для перехвата ошибок, например, при сбое подключения к БД?
  • a) `Status`

    b) `Link Out`

    c) `Switch`

    d) `Catch`

  • Принцип "минимальных привилегий" означает, что:
  • a) Система должна иметь минимальное количество пользователей.

    b) Пользователь должен иметь доступ только к ресурсам, необходимым для его работы.

    c) Пароли пользователей должны быть минимальной длины.

    d) Следует использовать минимальное количество реле.

  • Что произойдет, если в потоке из урока к считывателю приложить карту, которой нет в таблице `users`?
  • a) Поток остановится с ошибкой.

    b) Узел `MySQL` вернет пустой массив, и `Switch` направит поток по ветке "Not Found".

    c) Дверь откроется, так как нет запрещающего правила.

    d) Контроллер перезагрузится.

  • Для чего используется таблица `access_log`?
  • a) Для ускорения работы системы.

    b) Для хранения паролей пользователей.

    c) Для аудита безопасности и анализа инцидентов.

    d) Для временного хранения данных.

  • Вы подключаете электромагнитный замок, который открывается при снятии питания (NC-тип). К каким клеммам реле `RL-10` вы подключите цепь питания замка?
  • a) C (общий) и NO (нормально-открытый)

    b) C (общий) и NC (нормально-закрытый)

    c) Только к NO

    d) Только к NC

  • Какой протокол используется для интеграции с Microsoft Active Directory?
  • a) MQTT

    b) LDAP

    c) OAuth 2.0

    d) Modbus

  • В потоке Node-RED для СКУД узел `Delay 5s` используется для:
  • a) Задержки перед записью в лог.

    b) Того, чтобы дверь оставалась открытой на 5 секунд, после чего снова блокировалась.

    c) Предотвращения слишком частых считываний карты.

    d) Экономии электроэнергии.

  • Что является наиболее уязвимым местом в системе контроля доступа, реализованной по уроку?
  • a) Скорость работы MySQL.

    b) Физическая безопасность контроллера и считывателя.

    c) Количество ролей в системе.

    d) Длина UID RFID-карты.

    ---

    Мини-runbook: "Что делать, если..."

    COURSE-16-M04-RUNBOOK-01

    1. Диагностика: Проверьте физическое подключение USB-считывателя к контроллеру. Убедитесь, что узел `node-red-contrib-usbhid` (или аналог) установлен и настроен на правильное устройство HID.

    2. Решение: Переподключите считыватель. Перезапустите Node-RED. Проверьте `dmesg` в консоли Linux на предмет ошибок подключения USB-устройства.

    1. Диагностика: Подключите узел `Debug` после узла `MySQL`. Проверьте, что он возвращает. Если возвращается пустой массив `[]`, значит, UID карты в БД не совпадает со считанным.

    2. Решение: Скопируйте UID из `Debug`-сообщения от считывателя и убедитесь, что в таблице `users` в поле `card_uid` записано точно такое же значение (без пробелов, с учетом регистра).

    1. Диагностика: Сервис MySQL на контроллере не запущен или не отвечает.

    2. Решение: Подключитесь к консоли контроллера по SSH и выполните команду `sudo systemctl status mysql`. Если сервис неактивен, запустите его: `sudo systemctl start mysql`. Проверьте настройки подключения в узле `MySQL` (адрес `127.0.0.1`, имя пользователя, пароль).

    1. Диагностика: Проверьте соединение между выходом узла `Delay 5s` и вторым узлом `rpi gpio out`, который должен закрывать дверь.

    2. Решение: Убедитесь, что второй узел `rpi gpio out` отправляет в реле значение, соответствующее закрытому состоянию замка (в нашем примере `1`). Проверьте, что в узле `Delay` не стоит галочка "drop intermediate messages".