参考文档:
通过 Azure AD 应用程序代理远程访问本地应用程序
The reply URL specified in the request does not match the reply URLs configured for the application
为什么要配置Azure sso?
原因:
客户要求为EMR集群核心组件配置基于Microsoft Azure
的SSO,通过Azure AD
应用程序代理远程访问EMR集群本地应用程序
客户提出该要求主要出于两点考虑:
- 安全性
客户和我们是跨国的,我们都需要访问EMR集群里的本地应用程序,如果不采用类似Azure AD这种应用程序代理的方式,可能需要开通公网代理访问,这样风险极大. - 便捷性
EMR集群组件繁多,每个组件都有自己独立的账户认证体系,用户访问应用时,需要记录多个账户名密码,极其不便.
一. 方案选型
在网上搜寻关于airflow配置sso的现成案例,主要遇到两个问题:
- 介绍详细的版本不匹配
- 版本匹配的说的又很笼统
相关的资料很有限,大部分坑只能自己踩
Azure AD支持的身份验证方式主要有以下三种:
LDAP
SAML
OAUTH2
其中: 客户内部不使用LDAP
而airflow2版本目前全部基于flask-appbuilder
来做身份验证和鉴权,
flask-appbuilder
目前不支持SAM
L,所以改动起来工作量比较大
基于以上考虑,使用基于OAUTH2
的身份认证协议来进行airflow单点登录配置
二. 单点登录配置
2.1 Airflow配置ssl登录
为什么要配置ssl登录?而不是采用默认的登录方式?
原因:
airflow安装后,默认使用http协议访问
而Azure AD配置基于OAUTH2
的应用程序代理时,需要配置重定向url
重定向url要求填写为https
如下图:
配置https方式登录,需要提供相关证书.(airflow webserver
服务节点)
我们当时采用的是运维同事帮忙申请的经过认证的证书
当然也可以使用自签名的免费证书,不过登录的时候会有提示,忽略就好了
可在该网站生成免费的https证书:
FreeSSL.cn
证书生成后,需要将key和cert文件上传至webserver服务器本地目录下
之后,需要修改airflow.cfg
文件,根据https证书上传路
配置web_server_ssl_key
,web_server_ssl_cert
两个参数的值,
以下为一个示例:
vi airflow.cfg
#当web_server_ssl_key,web_server_ssl_cert均不为空时,ssl生效
web_server_ssl_key = /opt/modules/airflow/cert/*.com.key
web_server_ssl_cert = /opt/modules/airflow/cert/*.com_bundle.pem
配置结束之后,重启airflow webserver
,之后airflow会切换为https访问
2.2 Azure配置Airflow代理
首先使用微软账号登录以下网站:
https://portal.azure.com
在主页中选择Azure Active Directory
2.2.1 企业应用程序配置
选择Enterprise applications
–>New application
,根据界面提示创建新的企业应用程序
需要注意Application proxy配置:
1. Internal Url值为airflow配置ssl之后的内网地址
2. Translate URLs In Headers以及Application Body两个配置项都要选择no,否则会出现airflow界面访问异常的情况
为什么要这样配置请参考问题3.4
2.2.2 应用程序注册配置
界面选择App registrations
–>New registration
,注册应用程序,之后按照界面提示配置即可
需要注意如下配置:
Overview
overview这里,需要注意以下两个配置:
Application (client) ID, Directory (tenant) ID 客户端id及租户id后续配置airflow的时候需要用到
Authentication
这里需要注意以下配置:
重定向url里需要配置两个值
一个是企业应用程序的主页url
一个是在主页url后面添加/oauth-authorized/azure
为什么要这样配置请参考问题3.3
certificates & secrets
这里需要生成一个新的秘钥,并拿到秘钥的value值,后续配置airflow的时候需要用到
2.3 airflow webserver.py配置
需要修改websever.py
相关配置,以下是一个实例demo
需要替换以下值:
{your_clientid}
替换为2.2.2中提到的Application (client) ID
值
{your_tenant_id}
替换为2.2.2中提到的Directory (tenant) ID
值
{your_secret_value}
替换为2.2.2中提到的生成秘钥的value
值
import os
from flask_appbuilder.security.manager import AUTH_OAUTH
CSRF_ENABLED = True
AUTH_TYPE = AUTH_OAUTH
# 这里一定要配置创建用户,否则首次登录的时候会出现无限重定向最后访问失败的问题
AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE = "Admin"
OAUTH_PROVIDERS = [{
"name": "azure",
"icon": "fa-windows",
"token_key": "access_token",
'remote_app': {
# 该设置与应用程序id一致
'client_id':'{your_clientid}',
# 该设置与证书和密码中的客户端密码值一致
'client_secret':'{your_secret_value}',
# 该设置为https://login.microsoftonline.com/{租户id}/oauth2
"base_url": "https://login.microsoftonline.com/{your_tenant_id}/oauth2",
'client_kwargs':{
'scope': 'User.read email openid profile basic users name preferred_username upn',
# 该值设置为应用程序id
"resource": '{your_clientid}',
},
"request_token_url": None,
# 该值为https://login.microsoftonline.com/{租户id}/oauth2/token
"access_token_url": "https://login.microsoftonline.com/{your_tenant_id}/oauth2/token",
# 该值为https://login.microsoftonline.com/{租户id}/oauth2/authorize
"authorize_url": "https://login.microsoftonline.com/{your_tenant_id}/oauth2/authorize",
}
}
]
配置结束之后,重启airflow webserver
之后通过企业应用程序里配置的主页url即可访问airflow
2.4 通过azure代理访问airflow
访问如下网站,在这里能够看到你的微软应用,如下图:
https://myapplications.microsoft.com/
选择airflow对应的应用,即可访问,如下图,配置完成!
三. airflow配置sso踩过的坑及解决方案
犹记得当时配置的时候很是痛苦,碰到了很多奇怪的问题,踩了很多坑.
不过因为当时时间紧迫,有些问题没来的及详细记录.
时间过去比较久了,只能尽可能的把有记录的坑分享一下,希望后续大家不要遇到类似的问题能快速解决
3.1 BadGateway:This corporate app can’t be accessed.
该问题很基础:
基本排查方向就两个
- airflow webserver是否正常启动
- 配置的代理主页url是否有误
3.2 Ariflow界面访问报错: invalid client secret is provided
原因:
提供的秘钥错误,应该提供的是秘钥的值(value),这里很容易配置成秘钥的id,导致无法访问
与该问题类似的错误还有客户端id或者租户ID的值配置成对象ID,导致airflow无法访问.
特别是英文不好的同学! 这里需要细心一点!
3.3 代理访问报错: The reply URL specified in the request does not match the reply URLs configured for the application
该问题是一个比较经典的问题
原因:
当我们访问airflow
配置的外网代理地址时,会进行重定向.
而在配置应用程序注册时,也有一个重定向url的配置,如果两个配置不匹配,就会抛出这个错误.
重定向url的正确配置,我们可以通过截取浏览器的url值解析出来
确保我们配置的重定向url与实际跳转的url一致即可
注意:
这里会遇到一个奇怪的问题,
当我配置的重定向url是外网代理的主页地址时,报错会指向: {主页url{/oauth-authorized/azure
当我配置的重定向url是 {主页url{/oauth-authorized/azure,报错又会指向主页地址
最终,我将两个地址都添加到重定向url配置解决了这个问题.
该问题详细的解决方案可参考如下官方文档,有很详细的视频讲解:
The reply URL specified in the request does not match the reply URLs configured for the application
3.4 Airflow访问报错: CSRF Warning! State not equal in request and response.
界面上具体报错如下:
Something bad has happened.
Please consider letting us know by creating a bug report using GitHub.
Python version: 3.7.5
Airflow version: 2.1.1
-------------------------------------------------------------------------------
Traceback (most recent call last):
File "/home/beebird/.local/lib/python3.7/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/home/beebird/.local/lib/python3.7/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/beebird/.local/lib/python3.7/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/beebird/.local/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/home/beebird/.local/lib/python3.7/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/home/beebird/.local/lib/python3.7/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/beebird/.local/lib/python3.7/site-packages/flask_appbuilder/security/views.py", line 695, in oauth_authorized
resp = self.appbuilder.sm.oauth_remotes[provider].authorize_access_token()
File "/home/beebird/python3.7/lib/python3.7/site-packages/authlib/integrations/flask_client/remote_app.py", line 74, in authorize_access_token
params = self.retrieve_access_token_params(flask_req, request_token)
File "/home/beebird/python3.7/lib/python3.7/site-packages/authlib/integrations/base_client/base_app.py", line 143, in retrieve_access_token_params
params = self._retrieve_oauth2_access_token_params(request, params)
File "/home/beebird/python3.7/lib/python3.7/site-packages/authlib/integrations/base_client/base_app.py", line 126, in _retrieve_oauth2_access_token_params
raise MismatchingStateError()
authlib.integrations.base_client.errors.MismatchingStateError: mismatching_state: CSRF Warning! State not equal in request and response.
该问题是折磨我最久的一个问题,一度让我怀疑人生,除了界面上的报错之外
截取浏览器的访问请求,发现其一直在几个页面循环跳转,最终因为重定向次数过多,导致访问失败,然后在界面上抛出上面的问题
共有以下几个可能原因:
- webserver_config.py配置问题
webserver_config.py需要添加类似配置,保证当用户首次登录的时候能够在airflow创建用户
AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE = "Admin"
- 企业应用程序代理配置中,Translate URLs In Headers以及Application Body两个配置项没有都选择no
这里一定要都选择no
3. 访问用户的权限问题
对该应用的权限为Member才能够访问airflow,否则也会报上面的问题