我的 Django 应用程序的所有视图都按预期工作,与签名 XML 相关的视图除外。 在新的 Ubuntu docker 映像上运行时,这些视图(特别是我的 SAML 元数据视图)会返回 502 Bad Gateway 错误。
Nginx 错误日志显示:
2024/01/15 16:04:04 [error] 14#14: *219 upstream prematurely closed connection while reading response header from upstream, client: 172.17.0.1, server: [my application].azurewebsites.net, request: "GET /sso/metadata/ HTTP/1.1", upstream: "
http://unix:/code/[my application socket file].sock:/sso/metadata/"
, host: "localhost:801"
上游套接字位置是指运行我的 django 应用程序的gunicorn服务器,这里的错误日志显示:
[2024-01-15 16:04:04 +0000] [10] [WARNING] Worker with pid 25 was terminated due to signal 11
除了信号 7 或 8 之外,其他日志显示相同。
我在 2024 年 1 月之前构建的所有映像(最后一个是 12 月 19 日)使用相同的包,相关视图未更改,但这些(旧的)不会呈现 502 Bad Gateway 错误。
我正在使用
Ubuntu 22.04
、Python 3.9.18
、nginx version: nginx/1.22.1
、gunicorn (version 20.1.0)
和 Django==3.0.14
所有相关文件在工作和非工作 docker 映像上都保持不变,并且两个映像都运行相同版本的 ubuntu (22.04)、python、nginx 和 Gunicorn。
当我在 Visual Studio 构建的 python 环境中本地运行代码时,相关视图没有问题。但是,当我在 Docker for Windows 中本地构建映像时,问题仍然存在,如果我在 Docker for Windows 上本地运行 12 月 19 日的映像(或任何更早的映像),问题就会再次消失。 这意味着我无法构建不出现此问题的新 docker 映像。
Python 视图返回 502 Bad Gateway 而不是签名元数据
from onelogin.saml2.auth import OneLogin_Saml2_Auth
def meta(request):
req = {
'https': 'on' if request.is_secure() else 'off',
'http_host': request.META['HTTP_HOST'],
'script_name': request.META['PATH_INFO'],
'server_port': request.META['SERVER_PORT'],
'get_data': request.GET.copy(),
'post_data': request.POST.copy(),
'query_string': request.META['QUERY_STRING']
}
auth = OneLogin_Saml2_Auth(req, custom_base_path=settings.SAML_FOLDER)
saml_settings = auth.get_settings()
metadata = saml_settings.get_sp_metadata()
errors = saml_settings.validate_metadata(metadata)
if len(errors) == 0:
return HttpResponse(content=metadata, content_type='text/xml')
else:
return HttpResponseServerError(content=', '.join(errors))
这里
settings.SAML_FOLDER
是我的SAML配置文件夹的路径。
解决问题所采取的步骤 我尝试深入研究有问题的视图,沿着视图插入中断,以便准确地弄清楚在创建错误的网关响应之前我可以在 python 代码中走多远。
这样做时,我发现在包含步骤
metadata = saml_settings.get_sp_metadata()
以及从 python3-saml 包导入的此方法中出现问题 onelogin.saml2.auth.OneLogin_Saml2_Auth -> get_settings -> get_sp_metadata
我发现问题出现在来自“https:”的 settings.py 文件的第 740 行: //github.com/SAML-Toolkits/python3-saml/blob/master/src/onelogin/saml2/settings.py':
metadata = self.metadata_class.sign_metadata(metadata, key_metadata, cert_metadata, signature_algorithm, digest_algorithm)
解压它,它只包含
OneLogin_Saml2_Utils.add_sign()
方法,最后解压它,当包含来自“https://github.com/SAML-Toolkits/python3-saml/blob/”的 utils.py 文件的第 738 行时,我遇到了问题master/src/onelogin/saml2/utils.py':
signature = xmlsec.template.create(elem, xmlsec.Transform.EXCL_C14N, sign_algorithm_transform, ns='ds')
在此行之后停止并不总是会呈现网关错误,但如果我在此行之后停止视图,大约 80% 的请求将呈现错误网关错误。 从现在开始,我在视图中包含的行越多,百分比就越高,当我包含从“https://github.com/SAML-Toolkits/python3-saml/blob/master/”到第 777 行的所有行时src/onelogin/saml2/utils.py' 我只在大约 100 个调用中完成了一次,并且包含更多行总是会出现错误的网关错误。
此视图会占用我的 CPU,这可能是问题的根源,但我不知道为什么它只会占用新图像的 CPU。
我进一步尝试使用最新版本的
gunicorn==21.2.0
,但没有效果,即同一行代码出现相同的问题。
我在工作和非工作图像上使用最新版本的 xmlsec
和 python3-saml
,分别为版本 1.3.13 和 1.16.0。
我尝试在 Ubuntu 20.04 而不是 22.04 上构建映像,同样没有效果,在同一行代码中遇到了相同的问题。
python
lxml
软件包已安装了某些软件包依赖项的最新版本,如果此软件包版本>=5.0.0
会导致我的gunicorn服务器在使用xmlsec
生成签名时崩溃,从而导致nginx呈现502 Bad Gateway
错误.
当基于 Windows 时,使用最新的 lxml 包不会使我的虚拟 python 环境崩溃,但仅当在 Ubuntu 上运行时才会崩溃。
这意味着在我的
lxml==4.9.4
文件底部添加 requirements.txt
解决了问题。