`
顽石
  • 浏览: 163443 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

openstack keystone外部认证

 
阅读更多

1.keystone集成需求介绍

    公司要搭建基于openstack的私有云平台,提供IAAS。私有云用户是公司员工,考虑到公司已经有一套单点登录认证系统,需要openstack的keystone身份认证服务能集成该认证系统。

    keystone提供openstack的认证授权服务,它实现了OpenStack的Identity API,除此之外它还负责提供目录服务(提供服务的url)。keystone缺省提供基于用户名口令、LDAP等认证方式,此外还可开发python认证模块来提供其它的认证方式。

2.keystone外部认证流程

    集成公司已有的认证系统需要使用到keystone的外部(external authentication)认证,整个认证过程如下图。

    

      1)、用户在openatck控制台(该控制台可基于openstack的Horizon进行改造或重新开发)的登录页面中输入用户名、口令等,提交到公司认证系统进行登录认证。

 

      2)、公司认证系统认证通过后,返回访问凭证(通常是访问token)、用户名。

 

      3)、openstack控制台通过http协议将第二步收到的访问token和用户名通过keystone提供的认证接口发给keystone,发送的http请求大致如下:

        POST http://172.19.106.242:5000/v2.0/tokens

        REMOTE_USER:  用户名

        EXTERNAL_ACCESS_TOKEN: 访问token

        Accept: application/json

        Content-Type: application/json

       

        {"auth" : { } }    

 

        REMOTE_USER头是keystone进行外部认证必须要有的,请求中存在该头keystone才会执行外部认证,其值为用户名;EXTERNAL_ACCESS_TOKEN头是自定义的,其值是公司认证系统返回的访问token。

        http body是json格式,只有auth属性,内容为空。其他的如口令等都不需要。

 

     4)、keystone收到该请求后,识别出认证请求中存在REMOTE_USER头,就进行外部认证的处理,主要是根据REMOTE_USER头中的用户名查询keystone的user表,看用户记录是否存在(所以需要将公司用户信息同步到keystone的user表中,不需同步密码字段),存在就通过了keystone的认证,后续处理流程和进行用户名/密码验证的相同,主要是颁发keystone的unscoped token等(该token不和具体的project/tenant绑定)。

        基于安全的原因,keystone会到公司认证系统验证访问token(EXTERNAL_ACCESS_TOKEN头中携带),确保该token是公司认证系统颁发,且没过期。

         该验证也可采用其他方式,如keystone回调openstack控制台来验证该访问token,或openstack控制台和keystone之间采用对称或非对称密钥,keystone对opentack传过来的签名进行验证(该签名放在另一个http头中,去掉EXTERNAL_ACCESS_TOKEN头)。外加iptables进行控制台ip地址限制。

          在这一步的处理需要修改keystone的代码,具体的代码修改将在下面给出。

    5)、返回keystone unscoped token给控制台。

 

3.涉及到的代码修改

    keystone代码修改(基于openstack havana版)位于两个文件中,/opt/stack/keystone/keystone/token/controllers.py (对应v2.0认证接口)和/opt/stack/keystone/keystone/auth/controllers.py (对应v3认证接口),实际的文件位置根据安装来定。

   第一个文件的修改位于def _authenticate_external方法中,需要注意的是由于keystone的http底层代码会将收到的REMOTE_USER头加HTTP_前缀后改成HTTP_REMOTE_USER(目前的havana版存在该bug),因此在该方法中的context对象中是获取不到REMOTE_USER头的,需要在该方法开头进行如下的修改:

   #如果REMOTE_USER头和HTTP_REMOTE_USER头都没有,则抛异常

   if 'REMOTE_USER' not in context.get('environment', {}) and 'HTTP_REMOTE_USER' not in context.get('environment', {}):

            raise ExternalAuthNotApplicable()

   #如果REMOTER_USER为None,则将HTTP_REMOTE_USER的值赋给它。     

   remoteUser = context.get('environment', {}).get('REMOTE_USER')

   if not remoteUser:

            context['environment']['REMOTE_USER'] = context['environment']['HTTP_REMOTE_USER']

 

 到公司认证系统验证访问token的逻辑略去。

 

 第二个文件的修改位于 def authenticate(self, context, auth_info, auth_context)方法中,和第一个文件类似,不过该文件中对外部认证的处理还有其他几个小问题,通过调试很容易发现并修改。

 

 

   

  • 大小: 16.2 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics