Node-RED:Руководство пользователя/Безопасность

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Безопасность[1]

По умолчанию редактор Node-RED никак не защищен, поэтому любой, кто знает IP-адрес и порт, может получить доступ к редактору, внести свои изменений и выполнить их развертку. Поэтому этот вариант подходит только в том случае, если вы работаете с Node-RED в проверенной сети.

Поэтому в этой статье мы опишем, как можно защитить Node-RED. Она будет поделена на 2 части:

  • Защита админского и редакторского API
  • Защита HTTP-нод, панели управления и статического веб-контента

Защита админского и редакторского API

Админский и редакторский API поддерживают два типа аутентификации:

  • Аутентификация с помощью имени пользователя и пароля
  • Аутентификация через любого поставщика OAuth/OpenID вроде Twitter или GitHub (добавлена в версии 0.17)

Аутентификация через имя пользователя и пароль

Чтобы добавить аутентификацию пользователя в API админа и редактора, впишите в файл «settings.js» следующее:

adminAuth: {
    type: "credentials",
    users: [{
        username: "admin",
        password: "$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN.",
        permissions: "*"
    }]
}

Свойство «users» – это массив объектов, каждый из которых представляет собой данные об одном пользователе. Соответственно, в нем можно задать несколько разных пользователей, у каждого из которых могут быть разные полномочия.

К примеру, код выше задает только одного пользователя «admin», который имеет полномочия делать в редакторе абсолютно все, а для входа в систему использует пароль «password». Пароль хэшируется при помощи алгоритма bcrypt.

Примечание

В старых версиях Node-RED для включения базовой HTTP-аутентификации в редакторе можно было использовать свойство «httpAdminAuth». Но сейчас она устарела, и лучше ее не использовать.

Генерирование хэша пароля

Чтобы сгенерировать хороший хэш пароля, можно воспользоваться инструментом командной строки «node-red-admin». Инструкции по его установке можно найти вот тут.

node-red-admin hash-pw

Этот инструмент запросит у вас пароль, который вы хотите использовать, а затем напечатает хэш, который затем можно скопировать и вставить в файл настроек.

В качестве альтернативы можно, находясь в папке установки Node-RED, запустить команду ниже:

node -e "console.log(require('bcryptjs').hashSync(process.argv[1], 8));" your-password-here

Аутентификация через OAuth/OpenID

Была добавлена в версии 0.17.

Если вы хотите настроить аутентификацию через внешний ресурс, то можете воспользоваться для этого большим диапазоном аутентификационных стратегий библиотеки «passport.js».

У Node-RED есть аутентификационные модули и для Twitter, и для GitHub. Поскольку эти стратегии предусматривают некоторый специфический код, разработчики сделали для него «обертку», чтобы ими было легче пользоваться. Но эти модули также можно использовать в качестве шаблона для аутентификации с помощью других похожих стратегий.

В коде ниже продемонстрировано, как настроить аутентификацию через Twitter без использования соответствующего аутентификационного модуля от разработчиков Node-RED.

adminAuth: {
    type:"strategy",
    strategy: {
        name: "twitter",
        label: 'Sign in with Twitter',
        icon:"fa-twitter",
        strategy: require("passport-twitter").Strategy,
        options: {
            consumerKey: TWITTER_APP_CONSUMER_KEY,
            consumerSecret: TWITTER_APP_CONSUMER_SECRET,
            callbackURL: "http://example.com/auth/strategy/callback",
            verify: function(token, tokenSecret, profile, done) {
                done(null, profile);
            }
        },
    },
    users: [
       { username: "knolleary",permissions: ["*"]}
    ]
};

В свойстве «strategy» имеются следующие опции:

  • «name» – название используемой passport-стратегии
  • «strategy» – модуль passport-стратегии
  • «label» и «icon» – надпись и иконка для страницы залогинивания. В свойстве «icon» можно вписать название любой иконки с FontAwesome
  • «options» – объект «options», который передается passport-стратегии при ее создании. О том, что для него нужно, читайте в документации используемой стратегии. О свойстве «callbackURL» читайте ниже.
  • «verify» – функция верификации, используемая стратегией. Если данные пользователя верны, она должна вызвать done(), где вторым параметром должен быть профиль пользователя. В нем должно быть свойство «username», используемое для сверки со списком корректных пользователей. Разработчики «passport.js» стараются стандартизировать объекты для профиля пользователя, поэтому это свойство должно быть у большинства стратегий.

Свойство «callbackURL» – это URL, на который аутентификационный поставщик перенаправит пользователя после завершения процесса аутентификации. Первой частью этого URL должен быть URL вашего редактора Node-RED, а затем должно идти «/auth/strategy/callback». К примеру, если доступ к редактору осуществляется по ссылке «http://localhost:1880», то в свойстве «callbackURL» нужно вписать «http://localhost:1880/auth/strategy/callback».

Как задать стандартного пользователя

Код ниже не будет пускать пользователя в редактор, пока он не залогинится.

В некоторых случаях требуется настроить для всех пользователей хотя бы какой-то уровень доступа к редактору. Как правило, это доступ «только для чтения». Для этого вам нужно будет добавить в настройку «adminAuth» свойство «default» – это задаст стандартного пользователя.

adminAuth: {
    type: "credentials",
    users: [ /* список пользователей */ ],
    default: {
        permissions: "read"
    }
}

Полномочия пользователей

До выхода версии 0.14 для пользователей можно было задать только два вида полномочий:

  • «*» – полный доступ
  • «read» – только для чтения

Но с выходом версии 0.14 появились новые возможности для настройки полномочий. Теперь значением в этом свойстве может быть и одна строка (как раньше), и массив с несколькими полномочиями.

У каждого метода в админском API есть полномочия, необходимые для доступа к нему. Модель полномочий – ресурсо-ориентированная. К примеру, чтобы прочесть данные текущего потока, пользователю понадобится полномочие «flows.read», а для обновления потока ему понадобится полномочие «flows.write».

Истечение срока действия аутентификационного токена

По умолчанию срок действия токена доступа истекает через 7 дней после его создания. Увеличение этого периода сейчас не поддерживается.

Период действия токена можно отредактировать с помощью свойства «sessionExpiryTime» в настройке «adminAuth». Он задается в секундах. К примеру, если вам нужно, чтобы период действия токена длился 1 день, вам нужно будет вписать следующее:

adminAuth: {
    sessionExpiryTime: 86400,
    ...
}

Доступ к админскому API

Теперь, задав настройку «adminAuth», мы можем получить доступ к админскому API. О том, как это сделать, читайте тут.

Аутентификация пользователей с помощью собственного кода

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

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

  • Сохраните код ниже в файл «<node-red>/user-authentication.js»
module.exports = {
   type: "credentials",
   users: function(username) {
       return new Promise(function(resolve) {
           // Пишем здесь код, проверяющий,
           // корректно ли это имя пользователя:
           if (valid) {
               // Если корректно, возвращаем объект «user».
               // В нем должны находиться
               // свойства «username» и «permissions».
               var user = { username: "admin", permissions: "*" };
               resolve(user);
           } else {
               // Если не корректно, возвращаем «null»,
               // чтобы показать, что такого пользователя нет.
               resolve(null);
           }
       });
   },
   authenticate: function(username,password) {
       return new Promise(function(resolve) {
           // Пишем здесь код, проверяющий,
           // корректны ли имя пользователя и пароль:
           if (valid) {
               // Если корректны, возвращаем объект «user».
               // Это эквивалентно вызову функции users(username).
               var user = { username: "admin", permissions: "*" };
               resolve(user);
           } else {
               // Если не корректны, возвращаем «null»,
               // чтобы показать, что таких
               // имени пользователя и пароля не существует:
               resolve(null);
           }
       });
   },
   default: function() {
       return new Promise(function(resolve) {
           // Возвращаем объект «user» для стандартного пользователя. 
           // Если стандартных пользователей нет, возвращаем «null».
           resolve({anonymous: true, permissions:"read"});
       });
   }
}
  • Редактируем свойство «adminAuth» в файле «settings.js», чтобы загрузить этот модуль:
adminAuth: require("./user-authentication")

Защита HTTP-нод

Маршруты, которые становятся уязвимы в результате использования нод «http in», можно защитить с помощью базовой аутентификации.

Это можно сделать, отредактировав свойство «httpNodeAuth» в файле «settings.js» и задав там имя пользователя и пароль, дающие доступ к этим маршрутам:

httpNodeAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."},

При редактировании свойства «pass» используется тот же формат, что и в свойстве «adminAuth». Более подробно читайте выше в разделе «Генерирование хэша пароля».

Доступ ко всему статическому веб-контенту, заданному в свойстве «httpStatic», можно защитить с помощью свойства «httpStaticAuth», использующего тот же самый формат.

Примечание

В старых версиях Node-RED в свойстве «pass» нужно было указать MD5-хэш. Он криптографически небезопасен, поэтому разработчики добавили возможность использования bcrypt-хэша, используемого в «adminAuth». В целях обратной совместимости MD5-хэш по-прежнему поддерживается, но использовать его мы не рекомендуем.

См.также

Внешние ссылки