本文要解决的问题是,如何在基于CentOS 7.3的OpenStack上配置单点登录(Single Sign On): 所使用的第三方认证是Google帐号,而认证方法是OpenID Connect.
本文分为理论和实际操作两大部分。
一、理论部分
理论部分很重要,因为如果单看下面的实际操作部分,可能不知道在干什么。所以,还是要先打好理论的基础,再看实际操作就比较好理解了。
这一部分的理论略显复杂,但已经有很多文章介绍得很清楚了,所以本文打算只做一些简介,同时推出讲得不错的文章。
首先,要了解什么是单点登录。简单来讲,单点登录就是借由一个第三方的帐号来登录一个应用(可能是网页应用或App等)。举个例子,借由微博帐号来登录知乎。
那么,这是怎么做到的呢?比较流行的做法是通过OAuth2协议。关于OAuth2,参加下面的文章:
http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
https://blog.yorkxin.org/2013/09/30/oauth2-1-introduction
https://blog.yorkxin.org/2013/09/30/oauth2-implementation-differences-among-famous-sites
https://en.wikipedia.org/wiki/OAuth#OAuth_2.0
而OpenID Connect是什么呢?它是建立在OAuth2之上的一个认证层。关于OpenID Connect,可以参见下面的文章:
http://openid.net/connect/
http://openid.net/specs/openid-connect-core-1_0.html
那么,有哪些公司支持OpenID Connect协议了呢?列表在这里:
http://openid.net/certification/
可以看到,Google、Microsoft、Redhat、Paypal等都已经支持了OpenID Connect. 也就是说,利用它们的帐号,都可以登录进支持OpenID Connect方式认证的网页应用或App. 比如,OpenStack作为Service Provider,它是支持OpenID Connect的,那么我们用Google帐号理论上就可以登录OpenStack了。本文正是介绍具体实现方式的。
那么,我们熟知的微信、微博的帐号可以登录什么样的应用呢?据笔者调查,应该是能够登录支持OAuth2的站点或应用。微信和微博的配置方式如下:
http://open.wechat.com/cgi-bin/newreadtemplate?t=overseas_open/docs/web/login/login
https://auth0.com/docs/connections/social/weibo
OpenStack能否用微信或微博登录呢?笔者目前的看法,是不允许的,因为Keystone不直接支持OAuth2.
二、实际操作部分:
以下介绍如何在基于CentOS 7.3的OpenStack上配置单点登录。
1. 配置 Google Developers Console,建立自己的项目
这一步是向Google注册一个web application,其目的就是:以此项目代表OpenStack,即代表SP(Service Provider),而将此项目注册到 Google IdP 中就等同于将SP注册到Google IdP中。
具体操作大致如下:
首先,进入Google Developers Console,点击左上角的“GoogleAPIs”,然后可以看到左边的导航栏上出现“API Manager”(即API管理器)的字样。见下图:
然后点击左边导航栏的“Credentials”(即凭证)和“OAuth consent screen”(即OAuth同意屏幕)进行配置。类型(Type)要选择“Web Application”(即网页应用)。配置完成后的样子见下图:
最后,记录下clientID和client secret,将来会用到。
2. 建立 Service Provider,即搭建OpenStack
在本步骤中,采用PackStack来搭建OpenStack. 具体参见:
https://www.rdoproject.org/install/packstack/
PackStack搭建的一般不是最新的OpenStack的代码,但也是比较新的。
3. 在OpenStack中创建对OpenID Connect方式登录的支持
3.1· 导入环境变量
这一步就是执行一个source命令
source ~/keystonerc_admin
keystonerc_admin是搭建了PackStack之后自然会有的一个文件。
3.2 创建用户组,以管理 Federation 的用户,名为"federation_group"
openstack group create --domain default --description "Federation User Group" federation_group
openstack group list
3.3 创建实验所需的项目, 名为"federation_demo_project"
openstack project create --domain default --description "Federation Demo Project" federation_demo_project
3.4 为"federation_group"用户组,在项目"federation_demo_project"及域"Default"中添加管理员角色
openstack role add --domain default --group federation_group admin
openstack role add --project federation_demo_project --group federation_group admin
3.5 Keystone 服务需要将实验中的 IdP 信息添加到系统中,创建 IdP 实例,IdP 名为"google"
openstack identity provider create google --remote-id https://accounts.google.com
+-------------+----------------------------------+
| Field | Value |
+-------------+----------------------------------+
| description | None |
| domain_id | 916eb48e3ff34c9eacb50bc0d730651e |
| enabled | True |
| id | google |
| remote_ids | https://accounts.google.com |
+-------------+----------------------------------+
openstack identity provider list
openstack identity provider show google
3.6 Keystone 需要创建 Mapping,用于管理 Federation 用户的权限
创建 Mapping 需要提供相应的映射规则,文件名为"google-mapping-rules.json",内容如下:
# google-mapping-rules.json
[
{
"local": [
{
"group": {
"id": "fae2fbfc826f43fda81eaa59bb843fc8"
}
}
],
"remote": [
{
"type": "HTTP_OIDC_ISS",
"any_one_of": [
"https://accounts.google.com"
]
}
]
}
]
创建的 Mapping 实例名为"google_idp_mapping":
openstack mapping create google-idp-mapping --rules ./google-mapping-rules.json
openstack mapping list
3.7 Keystone 服务需要为信任的 IdP 创建 Protocol 实例
Keystone 服务需要为信任的 IdP 创建 Protocol 实例,这是用于记录 IdP 使用的身份验证协议以及 IdP 与 Mapping 实例的对应关系,实例名为"oidc":
openstack federation protocol create oidc --identity-provider google --mapping google-idp-mapping
openstack federation list
openstack federation protocol list --identity-provider google
4. Service Provider基于配置文件进行配置
上面一节是关于在OpenStack环境中运行命令以建立Service Provider对IdP的认知的过程;但这还不够,本节介绍Service Provider中基于配置文件所进行的配置。
4.1 对keystone.conf的修改
Modify /etc/keystone/keystone.conf
[auth]
# Allowed authentication methods. (list value)
methods = external,password,token,oauth1,oidc
oidc = keystone.auth.plugins.mapped.Mapped
......
[federation]
# Value to be used to obtain the entity ID of the Identity Provider from the
# environment (e.g. if using the mod_shib plugin this value is `Shib-Identity-
# Provider`). (string value)
remote_id_attribute = HTTP_OIDC_ISS
...
trusted_dashboard = http://<your_machine_hostname>/dashboard/auth/websso/
4.2 下载与安装 mod_auth_openidc 插件
该插件是Apache server的插件,其实就是一个.so文件(动态链接库),用于帮助Apache服务器进行OpenID Connect的认证。
但是要注意,这个rpm包是要自己去下载的,而且它还有若干dependencies需要解决。具体如下:
下载与安装:
wget https://github.com/pingidentity/mod_auth_openidc/releases/download/v2.3.0/cjose-0.5.1-1.el7.centos.x86_64.rpm
wget https://github.com/pingidentity/mod_auth_openidc/releases/download/v2.3.0/mod_auth_openidc-2.3.0-1.el7.centos.x86_64.rpm
wget http://springdale.math.ias.edu/data/puias/unsupported/6/x86_64/hiredis-0.12.1-1.sdl6.x86_64.rpm
yum localinstall -y ./cjose-0.5.1-1.el7.centos.x86_64.rpm
yum localinstall -y ./hiredis-0.12.1-1.sdl6.x86_64.rpm
yum localinstall -y ./mod_auth_openidc-2.3.0-1.el7.centos.x86_64.rpm
4.3 修改Apache服务器的配置文件
文件地址:
/etc/httpd/conf.d/10-keystone_wsgi_main.conf
在VirtualHost段落中增加如下内容:
注:VirtualHost是Apache Server中的一个术语,目的是为了在一个机器上通过不同端口从而运行多个server
<VirtualHost *:5000>
...
OIDCClaimPrefix "OIDC-"
OIDCResponseType "id_token"
OIDCScope "openid email profile"
OIDCProviderMetadataURL https://accounts.google.com/.well-known/openid-configuration
OIDCClientID <your client ID>
OIDCClientSecret <your client secret>
OIDCCryptoPassphrase openstack
OIDCRedirectURI http://demo.sso.org:5000/v3/auth/OS-FEDERATION/websso/oidc/redirect
<Location ~ "/v3/auth/OS-FEDERATION/websso/oidc">
AuthType openid-connect
Require valid-user
LogLevel debug
</Location>
...
</VirtualHost>
4.4 更改horizon的local_settings配置文件
vim /etc/openstack_dashboard/local_settings
或
vim /usr/share/openstack-dashboard/openstack_dashboard/local/local_settings.py
这二者是同一个文件。
修改的内容如下:
# Enables keystone web single-sign-on if set to True.
WEBSSO_ENABLED = True
WEBSSO_CHOICES = (
("credentials", _("Keystone Credentials")),
("oidc", _("OpenID Connect"))
)
WEBSSO_INITIAL_CHOICE = "credentials"
5. 重启HTTP服务
重启之前,先确认一下下面文件是否存在
ls -l /etc/keystone/sso_callback_template.html
重启服务:
systemctl restart httpd
6. 一些注意事项
6.1 Trouble Shooting
遇到问题,一般去看log,主要的log所在有2个:
- /var/log/keystone/keystone.log
- /var/log/httpd/keystone_wsgi_main_error.log
6.2 重定向名与访问名不同的问题
有的时候会出现这样的错误:
the URL scheme (%s) of the configured " OIDCRedirectURI " does not match the URL scheme of the URL being accessed (%s): the \"state\" and \"session\" cookies will not be shared between the two!
这个时候可以做如下尝试(做一个或都做):
a. 修改配置文件,使得可以通过FQDN访问HTTP Server
vim /etc/httpd/conf.d/15-horizon_vhost.conf
修改ServerName和ServerAlias(即,要修改或添加demo.sso.org,因为配置在Google Developers Console里的重定向地址也是这个FQDN)
b. 修改下列配置文件:
仍然是奔着将IP地址修改为demo.sso.org的方向去的
cd /var/www/cgi-bin/keystone
vim keystone_admin
vim keystone_public
c. 修改下列文件:
vim /etc/httpd/conf/httpd.conf
然后修改ServerName为demo.sso.org(因为配置在Google Developers Console里的重定向地址也是这个FQDN)
d. 最后,还是别忘了重启httpd服务
6.3 测试OIDCProviderMetadataURL是否能够通过
需想一些办法使Google能够访问,因为要保证ServiceProvider能够获取到OIDCProviderMetadataURL所指向的内容,即能够访问 https://accounts.google.com/.well-known/openid-configuration
7. Keystone 有一个bug!
到最后,发现Keystone居然有一个bug!
这个bug容笔者过几日再公布。一个小问题,相信读者您如果一步一步照着坐下来,最后调试的时候也会发现这个bug.
8. 效果
几幅效果图如下:
参考文献
- https://www.ibm.com/developerworks/cn/cloud/library/cl-cn-keystonehorizonsso/index.html
- http://wsfdl.com/openstack/2016/02/01/Keystone-Google-Federation-With-OpenID.html
- http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
- https://blog.yorkxin.org/2013/09/30/oauth2-1-introduction
- https://blog.yorkxin.org/2013/09/30/oauth2-implementation-differences-among-famous-sites
- https://en.wikipedia.org/wiki/OAuth#OAuth_2.0
- http://openid.net/connect/
- http://openid.net/specs/openid-connect-core-1_0.html
- http://openid.net/certification/
- http://open.wechat.com/cgi-bin/newreadtemplate?t=overseas_open/docs/web/login/login
- https://auth0.com/docs/connections/social/weibo