[Nginx, Apache, Lua, Kubernetes] Магия 2-х строк на Lua или как донести исходные заголовки HTTP Authorization header-авторизации до web-сервиcа
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Статья будет полезна тем:
- кому необходимо задействовать несколько видов авторизации в одном запросе к серверу;
- кто хочет открывать сервисы мира Kubernetes/Docker в общий интернет, не задумываясь о способах защиты конкретного сервиса;
- думает, что всё уже кем-то сделано, и хотел бы сделать мир немного удобнее и безопаснее.
Предисловие
Сервисы, которые становятся доступны через Kubernetes, имеют богатый набор способов авторизации. Один из наиболее модных – это заголовок Authorization: Bearer — это, например: JWT-авторизация (JSON Web Token) с передачей множества ключей, а следовательно, и значений, в одном заголовке. Встречаются и Basic-авторизации, например для Registry (хранилище образов Docker). Данная авторизация не использует Cookie и автоматически добавляется браузером (кроме Safari — там есть нюансы, которые мы пока не решаем) ко всем запросам к серверу.
Проблема 1:
Не получается авторизоваться через Firefox & Safari в интерфейсе Storage OS, показывается Loader, и на этом всё.
Мини-гипотеза:
Проблема в проксировании. Быстрая проверка показала результат: если авторизация без использования проксирования (универсальный безопасный доступ по сертификату), то всё работает. Так в чём же дело?
Проанализировав сетевой стек, мы поняли, что используется заголовок Authorization, однако ранее, в ходе настройки проксирования сервисов Rancher, было выяснено, что этот заголовок передаётся проксируемому сервису и содержит данные авторизации по сертификату, поэтому было решено его просто удалять по завершении процесса авторизации (FakeBasicAuth).
Проблема 2:
Во многих web-серверах авторизация по персональному сертификату реализована через эмуляцию Basic-авторизации (по сути, вмешательство в запрос пользователя), вероятно с целью уменьшения изменений в основном коде web-сервера. Называется такой способ FakeBasicAuth. После установления такого заголовка web-сервером затирается заголовок Authorization, который приходит от пользователя.
Гипотезы:
1. Область видимости заголовка FakeBasicAuth поддаётся ещё большему ограничению, так что восстанавливается исходный заголовок для передачи на проксируемый ресурс таким образом, что будет передаваться только оригинальный заголовок, если он был.
2. Область видимости заголовка Authorization может быть сконструирована так, что заголовок будет сохранён до активации механизма FakeBasicAuth и восстановлен после.
Видимое состояние — цель:
Storage OS авторизует, можно настраивать этот сервис, сохраняя единый подход к открытию доступности сервисов во внешний интернет.
Дополнительная цель:
Унифицированный, быстрый и безопасный доступ по http с сохранением функциональности всех возможных сервисов, работающих по стандарту http (например, REST API для мобильного приложения или Registry Docker).
Как проверить?
- docker login registry-rancher.xxx.ru — используя ключи и логин/пароль.
- storageos-rancher.xxx.ru/#/login — используя логин и пароль из конфигов secret rancher.xxx.ru/p/c-84bnv:p-qj9qm/secrets/kube-system:init-secr… (не работает в Safari).
- registry-ui-rancher.xxx.ru — используя браузер и логин/пароль от Registry. Для внимательно читающих фишка: можно вместо стандартного docker login registry-rancher.xxx.ru использовать этот интерфейс — там встроено проксирование к Registry.
Проверка гипотез:
1. Исходя из предыдущего опыта, попробуем найти способ в интернете по таким запросам: apache authentification external basic via cert.
Нашлась более-менее адекватная статья про ldap
вот таким образом:
RewriteEngine on
RewriteCond %{IS_SUBREQ} ^false$
RewriteCond %{LA-U:REMOTE_USER} (.+)
RewriteRule . - [E=RU:%1]
RequestHeader set REMOTE_USER %{RU}e
И далее прокинуть заголовок в дополнительных заголовках через конструкцию
RequestHeader add Authorization "expr=%{env:zt-auth-before}" "expr=%{env:zt-auth-before} =~/.{1,}/"
Но, к сожалению, эта конструкция не подразумевает создания идентичного заголовка, заголовку запроса пользователя, да и env формируется некорректно.
Поэтому способ на основе стандартных rewrite-ов оказался бесполезным и сложным.
2. Если не можем стандартно, значит, надо обратиться к lua, ранее видели, что есть блоки обработки запросов, которые выполняются до обработки сертификатов, снова посмотрим на блок-схему из статьи lua_load_resty_core и инструкцию module_lua_writinghooks c конструкцией early.
Получается, что мы можем задействовать тот же самый скрипт (Как мы в ZeroTech подружили Apple Safari и клиентские сертификаты с websocket-ами), чтобы сохранить заголовок Authorization до замены им на FakeBasicAuth.
LuaHookAccessChecker /usr/local/etc/apache24/sslincludes/websocket_token.lua handler early
В Lua это теперь выглядит так:
require 'apache2'
function handler(r)
local fmt = '%Y%m%d%H%M%S'
local timeout = 3600 -- 1 hour
local auth = r.headers_in['Authorization']
r.notes['zt-cert-timeout'] = timeout
r.notes['zt-cert-date-next'] = os.date(fmt,os.time()+timeout)
r.notes['zt-cert-date-halfnext'] = os.date(fmt,os.time()+ (timeout/2))
r.notes['zt-cert-date-now'] = os.date(fmt,os.time())
if auth ~= nil then
r.notes['zt-auth-before'] = auth
end
return apache2.OK
end
Примечание:
Жирным шрифтом отмечены новые конструкции. И раз мы знаем, что env, полученный из Lua, доступен только для expr-выражений, добавляем конструкцию рядом с шифрованием zt-cert токена:
#исходящие Cookie пользователю
Header set Set-Cookie "expr=zt-cert=%{sha1:...
#передаём заголовки проксируемому сервису
RequestHeader add Authorization "expr=%{env:zt-auth-before}" "expr=%{env:zt-auth-before} =~/.{1,}/"
Доступность данных для передачи сервису проверяли через передачу данных обратно пользователю в браузер:
Header add Authorization "expr=%{env:zt-auth-before}" "expr=%{env:zt-auth-before} =~/.{1,}/"
Самое интересное здесь — это способ проверки наличия данных, чтобы не передавать заголовок проксируемому сервису, если он не пришёл снаружи от браузера пользователя. За это отвечает вторая часть конструкции:
"expr=%{env:zt-auth-before} =~/.{1,}/"
Завершение:
Готовых решений в интернете на текущий момент нет, потрачено около трех часов на поиск и попытки проверить вариации, так как не хотелось «изобретать велосипед».
Добавлено 5 строк, 3 из которых можно смело удалить.
Как вы думаете, какие? — Пишите ваши варианты ответов в комментариях к статье.
Я не хотел писать об этом опыте, так как по-сути — это всего 2 строки и заголовок Authorization дойдёт до адресата, но решил всё же поделиться информацией, так как здесь используется хороший багаж знаний предыдущих исследований о сертификатах (речь об этой статье habr.com/ru/company/zerotech/blog/509130). К тому же вряд ли найдутся смельчаки написать что-то своё и настолько простое на неизвестном языке.
===========
Источник:
habr.com
===========
Похожие новости:
- [Информационная безопасность, Lua, CTF] HackTheBox. Прохождение Traceback. Бэкдор, LUA, SSH
- [Системное администрирование, Серверное администрирование, DevOps, Kubernetes] Представляем Contour: направляем трафик к приложениям в Kubernetes (перевод)
- [Системное администрирование, IT-инфраструктура, Nginx, DevOps] Как случайно продолжить писать Web-GUI для Haproxy
- [Системное администрирование, DevOps, Kubernetes] Полноценный Kubernetes с нуля на Raspberry Pi
- [DevOps] Мастерим задание на деплой в GKE без плагинов, смс и регистрации. Одним глазком заглядываем Jenkins'у под пиджак
- Выпуск nginx 1.19.2 и njs 0.4.3
- [Системное администрирование, DevOps, Kubernetes] Цена tailing'а логов в Kubernetes (перевод)
- [Информационная безопасность, Серверное администрирование, DevOps, Kubernetes] Изучаем (отсутствующую) безопасность типичных установок Docker и Kubernetes (перевод)
- [MySQL, Облачные вычисления, MongoDB, Kubernetes] Как собрать гибридное облако с помощью Kubernetes, которое может заменить DBaaS
- [Системное администрирование, Nginx, *nix, DevOps] Отправка Nginx json логов с помощью Vector в Clickhouse и Elasticsearch
Теги для поиска: #_nginx, #_apache, #_lua, #_kubernetes, #_lua, #_kubernetes, #_apache, #_nginx, #_blog_kompanii_zerotech (
Блог компании ZeroTech
), #_nginx, #_apache, #_lua, #_kubernetes
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 21:11
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Статья будет полезна тем:
Предисловие Сервисы, которые становятся доступны через Kubernetes, имеют богатый набор способов авторизации. Один из наиболее модных – это заголовок Authorization: Bearer — это, например: JWT-авторизация (JSON Web Token) с передачей множества ключей, а следовательно, и значений, в одном заголовке. Встречаются и Basic-авторизации, например для Registry (хранилище образов Docker). Данная авторизация не использует Cookie и автоматически добавляется браузером (кроме Safari — там есть нюансы, которые мы пока не решаем) ко всем запросам к серверу. Проблема 1: Не получается авторизоваться через Firefox & Safari в интерфейсе Storage OS, показывается Loader, и на этом всё. Мини-гипотеза: Проблема в проксировании. Быстрая проверка показала результат: если авторизация без использования проксирования (универсальный безопасный доступ по сертификату), то всё работает. Так в чём же дело? Проанализировав сетевой стек, мы поняли, что используется заголовок Authorization, однако ранее, в ходе настройки проксирования сервисов Rancher, было выяснено, что этот заголовок передаётся проксируемому сервису и содержит данные авторизации по сертификату, поэтому было решено его просто удалять по завершении процесса авторизации (FakeBasicAuth). Проблема 2: Во многих web-серверах авторизация по персональному сертификату реализована через эмуляцию Basic-авторизации (по сути, вмешательство в запрос пользователя), вероятно с целью уменьшения изменений в основном коде web-сервера. Называется такой способ FakeBasicAuth. После установления такого заголовка web-сервером затирается заголовок Authorization, который приходит от пользователя. Гипотезы: 1. Область видимости заголовка FakeBasicAuth поддаётся ещё большему ограничению, так что восстанавливается исходный заголовок для передачи на проксируемый ресурс таким образом, что будет передаваться только оригинальный заголовок, если он был. 2. Область видимости заголовка Authorization может быть сконструирована так, что заголовок будет сохранён до активации механизма FakeBasicAuth и восстановлен после. Видимое состояние — цель: Storage OS авторизует, можно настраивать этот сервис, сохраняя единый подход к открытию доступности сервисов во внешний интернет. Дополнительная цель: Унифицированный, быстрый и безопасный доступ по http с сохранением функциональности всех возможных сервисов, работающих по стандарту http (например, REST API для мобильного приложения или Registry Docker). Как проверить?
Проверка гипотез: 1. Исходя из предыдущего опыта, попробуем найти способ в интернете по таким запросам: apache authentification external basic via cert. Нашлась более-менее адекватная статья про ldap вот таким образом: RewriteEngine on
RewriteCond %{IS_SUBREQ} ^false$ RewriteCond %{LA-U:REMOTE_USER} (.+) RewriteRule . - [E=RU:%1] RequestHeader set REMOTE_USER %{RU}e И далее прокинуть заголовок в дополнительных заголовках через конструкцию RequestHeader add Authorization "expr=%{env:zt-auth-before}" "expr=%{env:zt-auth-before} =~/.{1,}/"
Но, к сожалению, эта конструкция не подразумевает создания идентичного заголовка, заголовку запроса пользователя, да и env формируется некорректно. Поэтому способ на основе стандартных rewrite-ов оказался бесполезным и сложным. 2. Если не можем стандартно, значит, надо обратиться к lua, ранее видели, что есть блоки обработки запросов, которые выполняются до обработки сертификатов, снова посмотрим на блок-схему из статьи lua_load_resty_core и инструкцию module_lua_writinghooks c конструкцией early. Получается, что мы можем задействовать тот же самый скрипт (Как мы в ZeroTech подружили Apple Safari и клиентские сертификаты с websocket-ами), чтобы сохранить заголовок Authorization до замены им на FakeBasicAuth. LuaHookAccessChecker /usr/local/etc/apache24/sslincludes/websocket_token.lua handler early
В Lua это теперь выглядит так: require 'apache2'
function handler(r) local fmt = '%Y%m%d%H%M%S' local timeout = 3600 -- 1 hour local auth = r.headers_in['Authorization'] r.notes['zt-cert-timeout'] = timeout r.notes['zt-cert-date-next'] = os.date(fmt,os.time()+timeout) r.notes['zt-cert-date-halfnext'] = os.date(fmt,os.time()+ (timeout/2)) r.notes['zt-cert-date-now'] = os.date(fmt,os.time()) if auth ~= nil then r.notes['zt-auth-before'] = auth end return apache2.OK end Примечание: Жирным шрифтом отмечены новые конструкции. И раз мы знаем, что env, полученный из Lua, доступен только для expr-выражений, добавляем конструкцию рядом с шифрованием zt-cert токена: #исходящие Cookie пользователю Header set Set-Cookie "expr=zt-cert=%{sha1:...
#передаём заголовки проксируемому сервису RequestHeader add Authorization "expr=%{env:zt-auth-before}" "expr=%{env:zt-auth-before} =~/.{1,}/"
Доступность данных для передачи сервису проверяли через передачу данных обратно пользователю в браузер: Header add Authorization "expr=%{env:zt-auth-before}" "expr=%{env:zt-auth-before} =~/.{1,}/"
Самое интересное здесь — это способ проверки наличия данных, чтобы не передавать заголовок проксируемому сервису, если он не пришёл снаружи от браузера пользователя. За это отвечает вторая часть конструкции: "expr=%{env:zt-auth-before} =~/.{1,}/"
Завершение: Готовых решений в интернете на текущий момент нет, потрачено около трех часов на поиск и попытки проверить вариации, так как не хотелось «изобретать велосипед». Добавлено 5 строк, 3 из которых можно смело удалить. Как вы думаете, какие? — Пишите ваши варианты ответов в комментариях к статье. Я не хотел писать об этом опыте, так как по-сути — это всего 2 строки и заголовок Authorization дойдёт до адресата, но решил всё же поделиться информацией, так как здесь используется хороший багаж знаний предыдущих исследований о сертификатах (речь об этой статье habr.com/ru/company/zerotech/blog/509130). К тому же вряд ли найдутся смельчаки написать что-то своё и настолько простое на неизвестном языке. =========== Источник: habr.com =========== Похожие новости:
Блог компании ZeroTech ), #_nginx, #_apache, #_lua, #_kubernetes |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 21:11
Часовой пояс: UTC + 5