Взаимная аутентификация в приложении Cloud Foundry с NodeJS + express

Я разработал приложение NodeJs + экспресс, развернутое как Приложение Cloud Foundry в IBM Cloud. Я хочу выполнить взаимная аутентификация (сертификаты клиента и сервера), чтобы контролировать входящий трафик и запросы к моему приложению. Мои сертификаты генерируются Безопасный шлюз, как описано здесь, с моим приложением, настроенным как место назначения в облаке (для доступа из локальных клиентов).

Secure Gateway сгенерировал следующие pem-файлы: первичный, промежуточный и корневой сертификат сервера, а также целевой сертификат и ключ. В документации есть довольно четкий Пример Nodejs с использованием tls.createServer.

В моем сценарии есть некоторые отличия: Прежде всего, я нахожусь в противоположном сценарии (с локальными клиентами, подключающимися к облачному приложению через Secure Gateway, создающий туннель). Во-вторых, и это основная причина этого поста, мое приложение развернуто как CF-приложение.

Читая документацию CF о HTTP-маршрутизация, я понял, что облако IBM использует только порты 80 и 443, а затем пересылает запросы через HTTP на порты, которые приложение прослушивает (например, если мои NodeJs работают на порте 6001, и я вызываю конечную точку облака на порт 443, GoRouter перенаправит запрос через HTTP на правильный порт, добавив заголовок X-Forwarded-Proto, чтобы передать приложению информацию об исходном протоколе, используемом для запроса.

Имея это в виду (при условии, что это правильно), в моем коде NodeJs я не могу использовать что-то вроде https.createServer(opts, app), учитывая, что все запросы, поступающие в контейнер приложения, будут осуществляться через HTTP.

Чтение документов CF здесь Я понимаю, что можно указать CF пересылать сертификаты в мое приложение, но есть кое-что, чего я не могу понять.

Прежде всего, в чем разница между завершением TLS в Load Balancer или GoRouter? Каковы причины этого выбора?

Мой второй вопрос: как правильно обрабатывать сертификаты после их перенаправления в мое приложение в виде заголовков HTTP? Это связано с тем, что мой сервер NodeJs будет http-сервером, созданным с помощью express стандартным способом http.createServer(app).

Спасибо всем, кто поможет мне в этом разобраться. Очевидно, что если у вас есть какие-либо примеры или советы, это будет очень полезно.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
721
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Reading CF documentation about HTTP routing I figured out that IBM cloud only uses ports 80 and 443 and then forwards the requests via HTTP to the ports the app is listening to (for example if my NodeJs is running on port 6001 and I call the cloud endpoint on port 443, the GoRouter will forward the request via HTTP to the correct port, adding the X-Forwarded-Proto header to pass the application the information of the original protocol used for the request.

Having this in mind (assuming this is correct), in my NodeJs code I cannot use something like https.createServer(opts, app) giving that all the requests coming to the App Container will be via HTTP.

Это правильно.

First of all what is the difference between terminating TLS at Load Balancer or at GoRouter? What are the reasons behind this choice?

Это применимо только в том случае, если вы используете собственную платформу Cloud Foundry. Если вы развертываете приложения на платформе Cloud Foundry, управляемой кем-то другим, они примут это решение, и это не повлияет на вас как на пользователя.

Это выбор, который вам необходимо сделать как оператору. Есть некоторые компромиссы в зависимости от того, что вы решите делать.

  1. Вы можете завершить работу в LB. Обычно это самый быстрый способ, так как LB очень эффективно обрабатывают TLS / SSL. Затем LB может пересылать трафик на Gorouter в незашифрованном виде, что снижает нагрузку на Gorouter, но происходит за счет того, что трафик между ними не шифруется (может быть не так, в зависимости от требований безопасности). В этом сценарии LB несет ответственность за добавление заголовков x-forwarded-*.

    браузер -> HTTPS -> LB -> HTTP -> Gorouters -> HTTP -> Ваше приложение

  2. Вы можете использовать LB уровня 4 и сбалансировать соединения между вашими Gorouters. Это позволяет Gorouters прерывать TLS / SSL. Они довольно эффективны в этом, но менее эффективны, чем большинство LB. Это также обеспечивает шифрование на пути запроса до Gorouter. В этом случае ответственность за добавление заголовков x-forwarded-* лежит на Gorouters.

    браузер -> HTTPS -> LB -> HTTPS -> Gorouters -> HTTP -> Ваше приложение

  3. Вы можете завершить работу на LB, но открыть новый сеанс TLS / SSL между LB и Gorouters. Это наименее эффективный вариант, поскольку он требует завершения двух сеансов TLS / SSL, но он обеспечивает шифрование на пути запроса до Gorouter. Он также имеет тенденцию быть наиболее гибким при работе с LB не уровня 4 и может позволить вашей LB проверять HTTP-трафик, потому что вы завершаете сеанс на LB. В этом сценарии LB несет ответственность за добавление заголовков x-forwarded-*.

    браузер -> HTTPS (сеанс A) -> LB -> HTTPS (сеанс B) -> Gorouters -> HTTP -> Ваше приложение

Опять же, если вы не используете платформу Cloud Foundry, вы можете игнорировать это.

My second question is which is the correct way of handling the certificates once they are forwarded to my application as HTTP headers? This is due to the fact the my NodeJs server will be an http server, created with express in the standard way http.createServer(app).

Вам не нужно делать ничего особенного с тем, как вы создаете свой сервер. Все, что вам нужно сделать, это посмотреть заголовки x-forwarded-* и использовать их для принятия решений.

  1. Запрос пришел через HTTPS? Посмотрите либо на x-forwarded-proto, который должен быть установлен на https для запросов HTTPS, либо на x-forwarded-port, который должен быть установлен на 443 для запросов HTTPS.

  2. Был ли предоставлен сертификат клиента вместе с запросом? Посмотрите X-Forwarded-Client-Cert. Если он содержит сертификат, значит, клиент предоставил сертификат.

  3. Сертификат клиента действителен? Если ваше приложение получает запрос, значит сертификат клиента действителен. Вы знаете это, потому что платформа обрабатывает эту часть за вас. Поскольку платформа (LB или Gorouter) завершает соединение TLS / SSL, она обязана проверить сертификат. Если ваше приложение получает запрос и установлен x-forwarded-client-cert, значит, сертификат действителен.

  4. Как мне принимать решения об авторизации на основе сертификата клиента? Это немного сложнее, но обычно вы извлекаете сертификат из x-forwarded-client-cert, читаете / анализируете его и принимаете решения на основе содержимого сертификата (которое, как мы знаем, является действительным благодаря платформе). Скорее всего, вы будете смотреть на имя субъекта и относиться к нему как к имени пользователя. Затем найдите роли или разрешения для этого пользователя. Однако то, как вы с этим справитесь, зависит от вас как разработчика.

Надеюсь, это поможет!

Привет, Даниэль, прежде всего, большое спасибо за ваш ответ. Вы сделали это намного более понятным для меня. Я пытаюсь проверить полученный заголовок http от моего сервера узла, но я не вижу x-переадресованный-клиент-сертификат (но я вижу x- forwarded-proto заголовок). Я использую CF из IBM Cloud. Прочитав документ, я обнаружил, что, вероятно, мне нужно настроить router.client_cert_validation до тех пор, пока enable_ssl и client_cert_validation. Могу ли я поместить эту конфигурацию в манифест? Я не могу понять, как изменить эти параметры, потому что я не вижу никакой разницы, а заголовок XFC все еще не определен

HCF 17.09.2018 18:16

Это будут настройки конфигурации, которые вы делаете, если вы являетесь оператором платформы. Поскольку вы используете платформу IBM, вам нужно спросить их, поддерживается ли эта функция на их платформе. Это может быть сложно как поставщик общедоступного облака, учитывая, что сертификатам клиентов должны доверять их балансировщики нагрузки или Gorouters. Для этого потребуется, чтобы ваши клиентские сертификаты были подписаны известным ЦС, или чтобы вы добавили свой ЦС в их список доверенных сертификатов. Идк, я размышляю. Вам нужно будет спросить у IBM.

Daniel Mikusa 18.09.2018 04:13

Еще раз спасибо, Даниэль. Я пытаюсь получить элемент управления не на уровне приложения, но я не знаю, достижимо ли это в моем сценарии (т.е. заблокировать всех клиентов, у которых нет определенного сертификата, до достижения моего приложения). Я бы хотел, чтобы мой loadbalancer (или GoRouter) отклонял каждый запрос от клиентов, у которых нет (конкретного, а не только доверенного) сертификата, отклоняя рукопожатие, не достигая моего приложения вообще. Я дам вам знать, когда будет ясен весь этот сценарий.

HCF 19.09.2018 11:12

Так не работает. Платформа будет только проверять действительность и надежность сертификата клиента. Он в основном выполняет аутентификацию за вас. Ваше приложение должно выполнить авторизацию и определить, какой уровень доступа, если таковой имеется, получит клиент.

Daniel Mikusa 21.09.2018 14:28

Я обнаружил, что также присутствуют $ wscs, $ wssi, $ wssn и т. д., Но заголовок $ wscc (сертификат клиента, используемый для этого запроса) не пересылается на мой сервер Node. Я спрошу у поддержки, как мне получить информацию о входящем сертификате клиента.

HCF 24.09.2018 09:02

Другие вопросы по теме