zoukankan      html  css  js  c++  java
  • keystone 认证深度研究分析

    一、Keystone Token深度概述 
    Keystone作为OpenStack项目基础认证模块,目前支持的token类型分别是uuid、pkiz、pki、fernet。 
    首先,简要叙述一下这四种类型的原理及其优缺点。 
    uuid 比较简单,采用随机生成的序列(128位,以16进制表示)作为id,并构造token内容,需要持久化后端数据库支撑,比如MySQL数据库存储。优点,实现简单;缺点是持久化查询、每次访问都需要keystone相关服务进行认证。 
    pki(pkiz) 基于cms算法,token格式以PKIZ_开头,pki类的token 长度很长(pkiz只是对pki进行了一定程度的压缩),它将所有token的内容都放在了token中,并且认证不需要与keystone服务交互,直接采用相关的证书进行本地认证,这类似与传统的U盾技术,但是密钥是在keystone处生成好了之后,是不能够进行实时更新的,安全性相对较低,一旦被破解,相关的信息将被暴露,此时,如果对密钥进行更新,将导致前面生成的token不可用。它的缺陷在于,没有密钥的周期性更替机制(安全性大打折扣),同时,负载太大,部分rest接口,不能处理超长请求。在生产环境中,极不推荐这种方式。 
    fernet 是当前主流推荐的token格式,这种方式相较于前几种类型,是当前比较均衡的一种方式。它不需要后端持久化存储,与pki类似,但是在认证上,仍然需要与keystone进行交互。它的token结构,采用了特定的数理结构设计(包括socoped类型、user信息等等),结合加密技术,重要的优点是它的轮询替换算法。简要叙述一下fernet密钥的原理,默认的轮换长度是3,当以keystone-manage fernet-setup生成密钥时,会看到0、1两个索引表征,这分别是什么意思呢?在此,需要提一下三个概念,primary key(主密钥,用于加密、解密token)、secondary key(次次密钥,用于解密token)、staged key(次密钥,用于解密token),那么上述0 表示的是staged key,1 表示的是primary key,primary key相比较另外两种key,它的索引最高,并且可以加密、也可以解密;staged key 相较于secondary key是它更有机会变为primary key。也就是说,fernet的密钥不是不变的,并且可以周期性轮转,不同认证节点之间的更新频次可以相差1。这安全性大大提高,keystone 进行认证的时候,依赖于这些密钥进行解密,从而进一步实现认证。 
    在分析了上述四种token格式后,毋庸置疑,fernet是比较靠谱,且性能相对较优的格式。但是,如果仅从这些分析上,不足以保证fernet的优势,说服力还不够。下面两节,将分别从认证原理、及历史经验数据上做探究分析。fernet是当前比较合适的方式,这并不表示fernet就是最优的token方式。在后面的分析上,尽可能提出更优的方案。 
    二、openstack认证 
    Openstack项目的认证技术,除了与keystone认证服务相关,也离不开众多的中间件的处理,如典型的keystone/middleware。首先,任何的服务在使用之前都需要获取token,token的生成,按照各种token的格式,uuid是存储在持久化后端数据库中,其他方式采用加密技术,token ID中包含了token数据的信息。有了token后,所有服务在发送请求时,需要将token ID作为请求字段,否则,直接抛出异常。而token ID的认证,主要依赖于中间件组件的处理。在下一小节中,重点说明。 
    在介绍认证原理之前,必须明确几个概念,cache、revoke、service-token、user-token、expiration,其中cache就是缓存,在keystone中常用的缓存工具是memcache,它在内存中开辟一块空间,用于存放token,优点不用多说,会大大缩短获取token的时间,并且验证时间也缩短了;revoke是回收机制,keystone中的token过期回收机制,会根据token的过期时间作响应或者人为主动发出的token回收请求;service-token在请求头中用X-Service-Token表示,是M版后,keystone认证所改进的技术,它主要是区分普通的用户的请求和服务请求,区分的原因是引入了过期token的使用,P版将会更加强化这一概念,并且过期token的使用,只发生在服务请求中;user-token就是普通用户的请求,在请求头中用X-Auth-Token表示;expiration,即过期时间,在keystone中有两处过期的概念:token的过期时间、cache的过期时间。简要叙述一下,cache的过期时间的设定,一般我们认为,cache存储的时间越久越好,但是cache的容量有限,并且,它占据着内存的空间,因此cache内存的大小实际存在一个理论上的“极值”设定,超过了这个大小,将会影响服务的响应处理,除了这一点,另外就是过期时间,考虑到过期token,即使存储在cache中,它也认证不通过,但是,如果cache中不存在的话,需要keystone服务去获取并且验证,这个开销比存储在cache中的开销要大。虽然如此,考虑一种高压情况,cache的存储,我们希望有效的token存储越多越好,过期的token,我们只存储一个index值,这样不会占据太多的空间,并且认证过程中,很快能够检测出过期token。在下一段的改进性能优化上,进一步说明。 
    正式进入openstack认证原理的介绍。openstack的项目,依赖于keystone项目进行认证,借助于中间件的处理.Token包括两部分,分别是token ID、token Data,token Data是核心,包括用户的信息、角色信息、服务信息、服务入口等等。Openstack认证,首先去cache中,查询是否存在对应的Token,如果存在,则进一步验证token是否被回收。此流程很简单;如果cache中不存在的话,keystone服务会去获取token的信息,并调用对应的driver去验证token,不同格式的token处理上有些差异,pki(pkiz)直接本地认证即可;其它两种方式都需要和keystone服务交互。如果获取并认证通过了,则需要将token的信息加入到cache中,否则,认证不通过,返回结果。具体流程,如下图所示。

    三、结合实际探究分析 
    回顾历史经验数据,曾经做过一个压力测试,验证token的抗压能力,uuid、fernet、pkiz的模式,得出的结论是fernet相对结果较好。我们的测试用例是nova list,这个结果,现在来看的话,有着它的必然性。能想到的keystone认证的瓶颈,主要是token 过期时间、cache的大小、时长、服务的worker数、数据库的性能。 
    fernet的数据性能最好,原因是它不需要后端持久化操作,并且token的认证,使用的是密钥进行解密,能够直接得出token Data的信息,从而进行token的过期认证,它的失败原因,只可能是token过期了,或者是token放到了cache中,但是已经被回收了。归根到底,还是token过期了。之前做的压测,设置的work数是8个,所以,当压力达到3千以上的时候,进程本身有一定的负载上限,因此在处理上,会出现多数的等待,我们看到获取token的那条命令,出错概率相对较低,原因是生成token的流程,没有后端数据库的操作,因此,比较流畅。有部分出错了,原因是由于请求等待时间过长,如果一直没有进程在处理,那么将会抛出获取token时的认证异常。其它出错,在认证时候的异常,原因是由于压力增多,导致一条请求的处理流程被拉长,token的过期时间也设置的较短,并且也存在请求长时间没有得到处理而抛出的认证异常。因此,当我们增加服务节点或者提高work数的时候,压力问题会得到有效的缓解。 
    Pki系列的性能也不太好,原因就是token长度太长。虽然它采用的是自认证的方式,在请求传递过程中的负载,将会消耗很大的时间,并且采用cache的方式,会导致命中出现问题,因为cache有大小上限,因此,很容易出现之前已经存在于cache的token,会被替换出去,从而影响后续的认证流程。它的请求传递开销,是它致命的缺陷。抗压能力较弱(此处说的是只有一台服务器的情况下)。 
    uuid的实现简单,但是抗压能力,是比较差的,因为它涉及大部分的持久化操作,数据库的性能直接影响压力测试的结果。常规情况下,我们不会单独再用一台数据库节点,因此,数据库性能不会很高,并且当数据库达到一定压力的时候,本身连接数据库就会变得很慢。 
    在上述分析中,我们从历史数据得出的部分解答。从近期的调研分析来看,openstack的服务在使用之前都需要认证,认证如果变得很快,那么openstack整体的服务性能将大大提升。认证过程中,除了增加服务数的方法、提高服务进程数外,token的cache命中率,也是有效提高认证的方法之一。除此之外,可信认证的充分利用,比如将某些服务发送的请求,去掉部分认证的环节,尤其是过期token的引入。 
    四、性能提升 
    为了提升token的认证能力,假设我们的使用场景是抗压能力测试,没有其他操作干扰,还是以nova list作为测试用例,我们以rest接口作为测试方法,没有超时限制,fernet作为token的格式,并且将token的时长调大,理论上只要token过期时长足够大,成功率,应该是能够达到100%。如果针对这个测试用例,非要找出出错的可能性,只可能出现在token过期。当我们引入过期token可再使用时,那么成功率将更加有保障。 
    在上述分析中,我们得出影响性能的几个关键因素:服务能力数(认证服务节点数量)、服务进程数(worker数量)、token的格式、cache的大小设置,cache策略。 
    服务能力数,即设置多少台服务节点是合适的,这个问题,需要考虑实际部署的机器的性能,因此,我们只有通过测试,这个值的大小大致是可以确定的。我们可以通过rest请求的响应时间作为参考值,我们需要提前预估一下响应时间的最大时间,即用户能够接受的时长,这个也是分请求的,比如创建虚机的请求,它涉及多个流程,它的响应时长的设置,应该是每个子操作响应时长的总合,因此,我们只需要设计好原子操作的响应时长。当合理的原子请求不能在规定的时间内得到响应,说明服务器服务需要优化,资源需要增加。因此,rest请求的响应能力,是判定服务能力的重要的参考依据。我们可以通过压力测试,找到服务能力的数值。 
    服务进程数,当服务器性能允许的情况下,这个数值越大,表示服务能力越强。但是,当进程太多,会拖慢机器的性能,这个值,在理论上也存在极值。一般情况下,我们开启32 或者64进程。具体的检测方法同上。也可以通过rest请求的压力测试得出。 
    token的格式,从上述的几种token的逻辑处理上,毋庸置疑,fernet的优势非常明显。 
    cache的大小设置,如果条件允许,并且token会被多次利用的概率较大,cache大小设置大一点。另外,在实际的生产环境中,获取了token后,95%的情况下,token会需要被验证,因此,token的改进措施,就是在生成了token后,就可以将token加入到cache中,这样在验证的时候,直接可以通过cache机制认证。这一点需要一定的cache大小空间的支撑,在下面的cache策略中再详述。 
    cache策略,在当前keystone服务中,token认证通过了,会被加入到cache中。token过期或者达到缓存时长,将会从cache中移除。如果token被回收,存储在cache中token会被标记为Invalid Token。Keystone发展到O版,service-token引入,并且允许过期token的使用,在私有云环境下,尤其是内部使用的项目,在cache策略上,service-token认证的流程,应该可以简化,甚至注释掉。但是,前面的策略只是某些个列情况下,当前比较优化的方案是,当token生成了后,直接将token放入cache中,在正常的业务流程中,该token会被用来发送请求。这样的话,在压力负载较大的情况下,优势会比较明显。 
    以上仅是个人的观点,如有问题,请及时与我探讨分析。

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 传球游戏
    Java实现 蓝桥杯VIP 算法训练 Hanoi问题
    Java实现 蓝桥杯VIP 算法训练 蜜蜂飞舞
    Java实现 蓝桥杯VIP 算法训练 奇偶判断
    Java实现 蓝桥杯VIP 算法训练 传球游戏
    Java实现 蓝桥杯VIP 算法训练 Hanoi问题
    Java实现 蓝桥杯VIP 算法训练 Hanoi问题
    Java实现 蓝桥杯VIP 算法训练 蜜蜂飞舞
    Java实现 蓝桥杯VIP 算法训练 蜜蜂飞舞
    Qt: 访问容器(三种方法,加上for循环就四种了)good
  • 原文地址:https://www.cnblogs.com/menkeyi/p/6995372.html
Copyright © 2011-2022 走看看