Обработка URL-адреса Flask для порта

У меня есть Kibana (часть стека elasticsearch), работающая на xx.xxx.xxx.xxx:5601. Поскольку Kibana не имеет собственной аутентификации, я пытаюсь включить ее в свою настройку входа в флягу. Другими словами, если кто-то попытается посетить xx.xxx.xxx.xxx:5601, мне нужно, чтобы страница была перенаправлена ​​на мою страницу входа во флягу. Я могу использовать декоратор @login_required для URL-адреса, чтобы добиться этого... но я не знаю, как настроить URL-адрес маршрута фляги для обработки порта 5601, поскольку он должен начинаться с косой черты.

@app.route("/")
@login_required

Какие-либо предложения?

РЕДАКТИРОВАТЬ @senaps: приложение 1 - это фляга, которая работает на 0.0.0.0, порт 9500, приложение 2 - это Kibana на основе node.js, которую я могу выбрать для запуска на локальном порту 5601, а затем выставить через nginx, или я могу напрямую опубликовать на IP:5601. В любом случае, он работает как «служба» при запуске и постоянно прослушивает 5601.

Постановка проблемы - приложение 2 должно быть заключено под логином приложения 1. Я не хочу использовать nginx для аутентификации приложения 2, а скорее для настройки входа в флягу приложения 1.

В настоящее время я использую gunicorn для обслуживания приложения flask и настроил обратный прокси-сервер nginx для маршрутизации к приложению flask. Следующее руководство: цифровой океан

Вариант 1. Приложение Node.js Kibana открыто для публики по IP: 5601.

server {
listen 80;
server_name example.com;

location / {
    include proxy_params;
    proxy_pass http://unix:/home/ubuntu/myproject/myproject.sock;
}}

Если я посещаю IP, он переходит в мое приложение для фляг, отлично. Я не могу понять, как обрабатывать URL-адрес просмотра фляги, если кто-то посещает IP: 5601. Вместо того, чтобы отправлять их в Kibana, он должен перенаправить в мое приложение flask для аутентификации.

Я попытался добавить еще один серверный блок для прослушивания на 5601 и proxy_pass в файл flask sock, я получаю сообщение об ошибке nginx, в котором говорится, что он не может привязаться к 5601, и просит меня убить слушателя на 5601. Но мне нужно, чтобы Kibana всегда работала на 5601. (если только я не смогу найти способ запустить эту службу через python flask).

Вариант 2. Приложение Kibana запускается на локальном хосте с портом 5601, подключенным к «/ kibana», чтобы не конфликтовать с «/», необходимым для flask. Затем он открывается через обратный прокси-сервер nginx.

server {
listen 80;
server_name example.com;

location / {
    include proxy_params;
    proxy_pass http://unix:/home/ubuntu/myproject/myproject.sock;
}
location /kibana/ {
    proxy_pass http://localhost:5601;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    rewrite /kibana/(.*)$ /$1 break;
}}

С этой настройкой можно получить доступ к Kibana, перейдя в IP/kibana. Но проблема с вариантом 2 заключается в том, что если у меня есть представление /kibana в моем приложении flask, чтобы поймать его, оно не вступит в силу, поскольку перенаправление на Kibana происходит в nginx, поэтому flask никогда не задействуется.

Я не смог найти много информации о стеке и т. Д., Поскольку большинство решений используют nginx для аутентификации Kibana, а не каких-либо других приложений Python.

Учитывая это, как бы я интегрировал ваше решение? Заранее большое спасибо за изучение этого.


person Arun Ramachandran    schedule 31.12.2017    source источник


Ответы (2)


так у вас есть 2 отдельных приложения не так ли? вы хотите, чтобы второе приложение работало только в том случае, если пользователь прошел аутентификацию в первом приложении.

Самым простым способом было бы использовать тот же самый db. Таким образом, вход в флягу будет проверять аутентификацию пользователя на основе того же db. с учетом сказанного, вы, возможно, не сможете справиться с сессией в полном порядке.

фокус в uwsgi над nginx. вы должны использовать Emperor режим uwsgi, чтобы оба приложения были развернуты.

@app.route("/")
@login_required
def function()

теперь вопрос может заключаться в том, как бы мы получили маршрут / второго приложения, если у первого приложения тоже есть этот маршрут. ну, это не будет проблемой, так как URL-адрес другой. но вам нужно настроить nginx для передачи запросов xx.x.x.x первому приложению и x.x.x.x:y второму приложению.

server {
    listen       80;
    server_name  example.org  www.example.org;
    root         /var/www/port80/
}

server {
    listen       5601;
    server_name  example.org  www.example.org;
    root         /var/www/port81/
}

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

person senaps    schedule 31.12.2017

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

import requests  # may require `pip install requests`

kibana_server_baseurl = 'https://xxx.xxx.xxx.xxx:5601/'

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
@login_required
def proxy_kibana_requests(path):
    # ref http://flask.pocoo.org/snippets/118/
    url = kibana_server_baseurl + path
    req = requests.get(url, stream = True)
    return Response(stream_with_context(req.iter_content()), content_type = req.headers['content-type'])

Другой вариант — использовать Nginx в качестве обратного прокси-сервера и использовать Nginx для аутентификации. Самый простой, если он соответствует вашим потребностям, — использовать базовую аутентификацию. https://www.nginx.com/resources/admin-guide/restricting-access-auth-basic/.

В качестве альтернативы вы можете проверить наличие пользовательского заголовка в конфигурации Nginx при доступе к приложению Kibana и перенаправить в приложение Flask, если он отсутствует.

Другой вариант — использовать существующий прокси-сервер аутентификации Kibana. Коммерческий вариант, Elastic x-pack — популярный вариант. Другой вариант OSS — https://github.com/fangli/kibana-authentication-proxy. Я тоже лично не пользовался.

person user650881    schedule 31.12.2017
comment
еще немного уточню, это точно не привязка к порту 5601, у меня фляга работает на отдельном порту. мое фляжное приложение размещено на AWS со статическим IP-адресом xx.xxx.xxx.xxx. Итак, скажем, у меня есть следующие представления (в качестве примера): когда я посещаю xx.xxx.xxx.xxx, он перехватывается @app.route(/), когда я посещаю xx.xxx.xxx.xxx/login, он перехватывается by @app.route(/login) и т.д... теперь у меня есть другое приложение, которое в настоящее время открыто для публики на xx.xxx.xxx.xxx:5601. вопрос в том, как мне поймать этот URL-адрес, чтобы я мог перенаправить его на соответствующий обработчик? - person Arun Ramachandran; 31.12.2017
comment
Часто в подобных случаях, когда flask обрабатывает аутентификацию, вы можете проксировать все запросы. То есть весь внешний доступ будет проходить через сервер flask и, в случае аутентификации, будет проксироваться на сервер kibana, чтобы пользователь никогда не связывался напрямую с сервером kibana. Сервер фляги не может видеть трафик на порту kibana. Если вы хотите, чтобы сервер flask просто установил заголовок или файл cookie и перенаправил на сервер kibana, сервер kibana необходимо изменить, чтобы проверить токен аутентификации и перенаправить на сервер flask, если он отсутствует. - person user650881; 01.01.2018
comment
@ArunRamachandran Я обновил ответ, чтобы показать, как вы можете проксировать трафик на сервер кибабы. Затем вы можете использовать правило брандмауэра и, в зависимости от вашей топологии, ограничить интерфейс привязки, чтобы ограничить доступ к серверу kibana. - person user650881; 01.01.2018
comment
я предпочитаю решить эту проблему, проксируя весь трафик с помощью flask - это имеет смысл. Базовая аутентификация Nginx означает, что пользователь должен дважды авторизоваться - войти в флягу, а затем авторизоваться nginx, я хочу избежать этого. Я вроде как понимаю, как работает ваш фрагмент catch all (очень умно), однако, когда я устанавливаю kibana_server_baseurl = staticIP:5601, фляга все еще не ловит его. Flask ловит любой статический IP/путь, но не staticIP:5601. Он по-прежнему открывает Кибану. @app.route начинается с /path, не знаю, как его настроить: 5601/. Это проблема? Мысли? - person Arun Ramachandran; 03.01.2018
comment
как вы сказали, если фляга никогда не сможет прослушивать трафик на порту 5601, возможно, это невозможно. Я также готов изучить базовую аутентификацию nginx, если смогу понять, как избежать двойной аутентификации. Другими словами, скажем, я установил базовую аутентификацию в конфигурации nginx. Пользователь входит в мое приложение flask, а затем переходит на страницу со встроенной панелью инструментов kibana через iframe. Теперь при рендеринге страницы nginx будет запрашивать аутентификацию. Есть ли способ заставить код предоставить это, чтобы пользователь этого не делал? Я читал о предварительном запросе ajax, но я не знаю, как это осуществить. - person Arun Ramachandran; 03.01.2018
comment
что касается третьего варианта пользовательского заголовка, мне понадобится помощь в его выполнении. Я думаю, что могу понять, как проверить пользовательский заголовок в nginx, и это предотвратит прямой доступ к Kibana. Однако мне нужно будет предоставить доступ к Kibana внутри моего фляжного приложения через iframe. Как мне указать собственный заголовок в URL-адресе, чтобы nginx снова не перенаправлял его на мою флягу? - person Arun Ramachandran; 03.01.2018
comment
@ArunRamachandran 1. С базовой аутентификацией Nginx перед сервером Kibana вы, вероятно, вообще больше не будете использовать сервер Flask. 2. Если вы проксируете весь трафик через порт 80, пользователь никогда не будет обмениваться данными через порт 5601. С описанной вами конфигурацией весь трафик будет проходить по этой цепочке: Client <-- port 80 --> Flask <-- port 5601 --> Kibana. В этом случае прямой доступ клиента к 5601 должен быть запрещен. 3. Опция пользовательского заголовка сложнее, чем другие опции. Я подозреваю, что вам будет проще найти один из других вариантов. - person user650881; 03.01.2018
comment
может быть, я полностью упускаю вашу точку зрения (я очень новичок во всей этой настройке, пытаясь учиться по ходу дела). я проксирую весь трафик на 80 в мое приложение фляги (см. настройку nginx в моем посте). В то же время мне нужно открыть порт 5601, чтобы IP-адрес ссылки iframe kibana: 5601 работал. Flask не может поймать трафик на IP: 5601. Я не могу запретить клиенту прямой доступ к 5601 с помощью flask. Вот где я застрял. - person Arun Ramachandran; 03.01.2018
comment
@АрунРамачандран. Комментарии не идеальны для этого обсуждения. Поскольку вы настроили его, вы больше не будете использовать порт 5601 для панели управления Kibana, а скорее будете использовать порт 80. Рискуя открыть кроличью нору, в зависимости от ваших потребностей можно поместить приложение flask на порт 5601 и переместить сервер Kibana на другой порт, поэтому вам не нужно перенастраивать клиентов. - person user650881; 03.01.2018