Цель:
Использовать OIDC из приложения Flask, работающего в контейнере Docker.
Фон:
IЯ создаю веб-приложение с Flask и хочу использовать Keycloak для предоставления доступа.Для этого я использую библиотеку Python flask_oidc.
Все сервисы запускаются локально с файлом docker-compose:
- Gunicorn, который запускает приложение Flask (порт 5000)
- Keycloak (порт 8080)
Я последовал примеру https://gist.github.com/thomasdarimont/145dc9aa857b831ff2eff221b79d179a и даже сократил свое приложение до этого.
Проблема:
- Запуск всех служб
- Перейдите к службе, требующей входа в систему (в примере
/private
) - Пользователь перенаправлен насервер Keycloud предлагает войти в систему.
- Пользователь входит в систему.
- Keycloak направляет пользователя обратно в приложение (
/oidc_callback
) - !!!Приложение Flask вылетает с ошибкой
OSError: [Errno 99] Cannot assign requested address
.
Это вызвано глубоко в flask_oidc
> oauth2client
> httplib2
при попытке подключения к серверу Keycloak.
Я думаю, что происходит из-за того, что библиотека пытается открыть соединение с сервером Keycloak, но пытается связать это с localhost
.Это, вероятно, завершается ошибкой, поскольку внутри контейнера Docker приложения связаны с 0.0.0.0
.
Что я пробовал:
[ WORKS ] Выполнитьприложение Gunicorn / Flask вне контейнера, и запустите Keylcoak внутри контейнера.
Это показывает (для меня), что все мои настройки и код отлично , но проблема заключается во взаимодействии Docker <-> flask_oidc +.
Вопрос : Кто-нибудь может это объяснить?Я действительно надеюсь, что у кого-то есть рабочая установка (Flask внутри докера с flask_oidc), и он готов поделиться этим.
ОБНОВЛЕНИЕ [5-12-2018] Я думаю, я понял это,Я использовал PyOIDC, чтобы вручную выполнить все шаги и иметь возможность отладки.
При запуске обеих служб в Docker на вашем собственном компьютере (localhost
) вы получаете конфликт:
- Пользователи переходят на
localhost:8080
, чтобы найти Keycloak, и localhost:5000
, чтобы найти приложение. - Приложение Flask запускается внутри контейнера, а
localhost
не разрешается на host а скорее к самому себе внутри контейнера. - Вы можете позволить Flask подключиться к
http://keycloak/
, используя сеть в контейнере, , но , тогда он возвращает всю конфигурацию в соответствии сэтот домен.Что плохо, потому что для внешнего мира это должно быть localhost:8080
.
Теперь, если у вас действительно есть доменные имена (например, keycloak.awesome.app и app.awesome.app), я думаюон будет работать нормально, так как он будет использовать внешний DNS для преобразования его в IP-адрес, который является правильным компьютером.
Бонус: PyOIDC может получить конфигурацию провайдера изKeycloak, так что больше не нужно печатать вручную для этого.Yay!
Новая настройка Для локального развития я решил сделать небольшую настройку следующим образом:
(1) Добавить в /etc/hosts
: 127.0.0.1 keycloak.dev.local
127.0.0.1 app.dev.local
(2) Добавьте к своей службе Flask в docker-compose.yml
: extra_hosts: #host.docker.internal is not accepted.
- "keycloak.dev.local:<YOUR IP ADRESS>"
- "app.dev.local:<YOUR IP ADRESS>"
(=) Теперь и вы, и приложение Flask можете получить доступ к keycloak.dev.local
и можете правильно отвечать!
Обратите внимание, что я все же предпочел бы решение лучше .Эта настройка завершается ошибкой, как только меняется мой IP-адрес.