Русский
Русский
English
Статистика
Реклама

Магия 2-х строк на Lua или как донести исходные заголовки HTTP Authorization header-авторизации до web-сервиcа

Статья будет полезна тем:

  • кому необходимо задействовать несколько видов авторизации в одном запросе к серверу;
  • кто хочет открывать сервисы мира 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 onRewriteCond %{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.OKend


Примечание:

Жирным шрифтом отмечены новые конструкции. И раз мы знаем, что 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
К списку статей
Опубликовано: 17.08.2020 10:13:59
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Блог компании zerotech

Nginx

Apache

Lua

Kubernetes

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru