Goal:
从 Docker 容器中运行的 Flask 应用程序使用 OIDC。
背景:
我正在使用 Flask 构建一个 Web 应用程序,并希望使用 Keycloak 来提供访问权限。为此,我使用 Python 库flask_oidc。
所有服务都使用 docker-compose 文件在本地运行:
- 运行 Flask 应用程序的 Gunicorn(端口 5000)
- Keycloak(端口8080)
我效仿了https://gist.github.com/thomasdarimont/145dc9aa857b831ff2eff221b79d179a https://gist.github.com/thomasdarimont/145dc9aa857b831ff2eff221b79d179a甚至将我的应用程序简化为这样。
Problem:
- 启动所有服务
- 导航到需要登录的服务(
/private
在示例中)
- 用户被重新路由到 Keycloud 服务器,提示登录。
- 用户登录。
- Keycloak 引导用户back到应用程序(
/oidc_callback
)
- !!! Flask 应用程序崩溃并显示
OSError: [Errno 99] Cannot assign requested address
error.
这是在内心深处造成的flask_oidc
> oauth2client
> httplib2
当尝试连接到 Keycloak 服务器时。
What I think发生的情况是库尝试打开与 Keycloak 服务器的连接,但尝试将其绑定到localhost
。这可能会失败,因为在 Docker 容器内,应用程序绑定到0.0.0.0
.
我尝试过的:
[WORKS] 在容器外部运行 Gunicorn/Flask 应用程序,并在容器内部运行 Keylcoak。
这(对我来说)表明我的所有设置和代码都是fine,但问题出在 Dockerflask_oidc+ 之间的交互中。
Question:
谁能解释一下吗?我真的希望有人有一个工作设置(带有flask_oidc的docker内部的Flask),并且愿意分享这个。
更新 [2018 年 5 月 12 日]我想我明白了。我使用 PyOIDC 手动完成所有步骤并能够进行调试。
当在您自己的计算机上运行 Docker 中的这两个服务时(localhost
)你会遇到冲突:
- 用户前往
localhost:8080
找到钥匙斗篷并localhost:5000
找到该应用程序。
- Flask 应用程序在容器内运行,并且
localhost
不解决host而是容器内的自身。
- You can让 Flask 连接到
http://keycloak/
使用容器中的网络,but然后返回该域下的所有配置。这很糟糕,因为对于外界来说这应该是localhost:8080
.
现在,如果您确实有域名(例如 keycloak.awesome.app 和 app.awesome.app),我认为它会正常工作,因为它会使用外部 DNS 将其解析为 IP 地址,即正确的机器。
Bonus:PyOIDC 可以从 Keycloak 检索提供程序配置,因此无需再手动输入。耶!
新设置对于本地开发,我决定进行一些设置,如下所示:
(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
并能正确应对!
请注意,我仍然更喜欢nicer解决方案。一旦我的 IP 地址发生变化,此设置就会失败。