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

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

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).

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


person HCF    schedule 14.09.2018    source источник


Ответы (1)


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

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

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

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

Это применимо только в том случае, если вы используете собственную платформу 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, вы можете игнорировать это.

Мой второй вопрос: как правильно обрабатывать сертификаты после их перенаправления в мое приложение в виде заголовков HTTP? Это связано с тем, что мой сервер NodeJs будет http-сервером, созданным с помощью express стандартным способом 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, читаете / анализируете его и принимаете решения на основе содержимого сертификата ( который, как мы знаем, действителен благодаря платформе). Скорее всего, вы собираетесь смотреть на имя субъекта и относиться к нему как к имени пользователя. Затем найдите роли или разрешения для этого пользователя. Однако то, как вы с этим справитесь, зависит от вас как разработчика.

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

person Daniel Mikusa    schedule 17.09.2018
comment
Привет, Даниэль, прежде всего, большое спасибо за ваш ответ. Вы сделали это намного более понятным для меня. Я пытаюсь проверить полученный HTTP-заголовок от моего сервера узла, но я не вижу ни одного x-forwarded-client -cert (но я вижу заголовок x-forwarded-proto). Я использую CF из IBM Cloud. Прочитав документ, я обнаружил, что, вероятно, мне нужно настроить router.client_cert_validation как пока enable_ssl и client_cert_validation. Могу ли я поместить эту конфигурацию в манифест? Я не могу понять, как изменить эти параметры, потому что я не вижу никакой разницы, а заголовок XFC все еще не определен - person HCF; 17.09.2018
comment
Это будут параметры конфигурации, которые вы задаете, если являетесь оператором платформы. Поскольку вы используете платформу IBM, вам нужно спросить их, поддерживается ли эта функция на их платформе. Это может быть сложно как поставщик общедоступного облака, учитывая, что сертификатам клиентов должны доверять их балансировщики нагрузки или Gorouters. Для этого потребуется, чтобы ваши клиентские сертификаты были подписаны известным центром сертификации или чтобы вы добавили свой центр сертификации в их список доверенных сертификатов. Идк, я размышляю. Вам нужно будет спросить у IBM. - person Daniel Mikusa; 18.09.2018
comment
Еще раз спасибо, Даниэль. Я пытаюсь получить элемент управления не на уровне приложения, но я не знаю, достижимо ли это в моем сценарии (т.е. заблокировать всех клиентов, у которых нет определенного сертификата, до достижения моего приложения). Я хотел бы, чтобы мой loadbalancer (или GoRouter) отклонял каждый запрос от клиентов, у которых нет (конкретного, а не только доверенного) сертификата, отклоняя рукопожатие, не достигая моего приложения вообще. Я дам вам знать, когда будет ясен весь этот сценарий. - person HCF; 19.09.2018
comment
Так не работает. Платформа будет только проверять действительность и надежность сертификата клиента. Он в основном выполняет аутентификацию за вас. Ваше приложение должно выполнить авторизацию и определить, какой уровень доступа, если таковой имеется, получит клиент. - person Daniel Mikusa; 21.09.2018
comment
Я обнаружил, что также присутствуют $ wscs, $ wssi, $ wssn и т. Д., Но заголовок $ wscc (сертификат клиента, используемый для этого запроса) не пересылается на мой сервер Node. Я спрошу у поддержки, как мне получить информацию о входящем сертификате клиента. - person HCF; 24.09.2018