keystone认证方式:UUID、PKI、Fernet;

知识点复习:

通俗的讲,token 是用户的一种凭证,需拿正确的用户名/密码向 Keystone 申请才能得到。如果用户每次都采用用户名/密码访问 OpenStack API,容易泄露用户信息,带来安全隐患。所以 OpenStack 要求用户访问其 API 前,必须先获取 token,然后用 token 作为用户凭据访问 OpenStack API。

公开密钥加密,也称为非对称加密(asymmetric cryptography,加密密钥和解密密钥不相同),在这种密码学方法中,需要一对密钥,分别为公钥(Public Key)和私钥(Private Key),公钥是公开的,私钥是非公开的,需用户妥善保管。如果把加密和解密的流程当做函数 C(x) 和 D(x),P 和 S 分别代表公钥和私钥,对明文 A 和密文 B 而言,数学的角度上有以下公式:

B = C(A, S)

A = D(B, P)

其中加密函数 C(x), 解密函数 D(x) 以及公钥 P 均是公开的。采用公钥加密的密文只能用私钥解密,采用私钥加密的密文只能用公钥解密。非对称加密广泛运用在安全领域,诸如常见的 HTTPS,SSH 登录等。

数字签名又称为公钥数字签名,首先采用 Hash 函数对消息生成摘要,摘要经私钥加密后称为数字签名。接收方用公钥解密该数字签名,并与接收消息生成的摘要做对比,如果二者一致,便可以确认该消息的完整性和真实性。

(1)UUID认证原理:

当用户需要进行操作时(比如访问nova创建虚拟机),用户拿着有效的用户名/密码先去keystone认证,keystone返回给用户一个token(即UUID)。之后用户进行其他操作(如访问nova),先出示这个token给nova-api,nova收到请求后,就用这个token去向keystone进行请求验证。keystone通过比对token,以及检查token的有效期,判断token的有效性,最后返回给nova结果。

缺陷:每次请求都要经过keystone进行验证,造成性能瓶颈。

1.用户输入用户名密码,发送给keystone。

2.Keystone验证用户名密码,并且生成token(UUID),发送给客户端。

3.客户端缓存UUID token

4.客户端发送具体的执行请求(nova boot)和UUID给keystone。

5.Keystone从http请求中获取token,并检查token是否有效

6.Token有效,处理请求,并返回客户端请求结果

7.Token失效,拒绝客户端请求,返回401。

UUID方式源码分析:

UUID token 是长度固定为 32 Byte 的随机字符串,由 uuid.uuid4().hex 生成。

def _get_token_id(self, token_data):    return uuid.uuid4().hex

生成的样例:144d8a99a42447379ac37f78bf0ef608

(2)PKI认证原理:

在keystone初始化时,keystone生成了CA的公钥CA.pem和私钥CA.key,同时keystone产生了自己的公钥keystone.pub和私钥keystone.key,然后将keystone.pub进行CA的签名,生成keystone.pem。

当用户拿着用户名/密码去keystone认证后,keystone将用户的基本信息通过keystone.key进行加密,并将密文作为token返还给用户。当用户拿着token发送请求时(例如访问nova),nova拿到用户token时,通过事先拿到keystone的证书keystone.pem(这一过程只需要进行一次)进行解密,获取用户信息。

对于用户的token,还需进行token的合法时间,以及token还是否存在进行判断。所以当nova每一次拿到token后还需向keystone询问一次token的失败列表,检查token是否失效。这一过程对于keystone的负载还是相当轻的,所以PKI还是有效解决了keystone性能瓶颈的问题。

小结:OpenStack服务中的每一个API Endpoint都有一份keystone签发的证书,失效列表和根证书。API不用在直接去keystone认证token是否合法,只需要根据keystone的证书和失效列表就可以确定token是否合法。但是这里还是会有每次都需要请求keystone去获取失效列表的操作,不可避免。

PKI的流程,首先需要使用 keystone-manage pki_setup命令生成CA及相关的令牌机制,其代码如下所示:

def _get_token_id(self, token_data):

try:

token_json = jsonutils.dumps(token_data, cls=utils.PKIEncoder)

token_id = str(cms.cms_sign_token(token_json,

CONF.signing.certfile,

CONF.signing.keyfile))   #DEFAULT_TOKEN_DIGEST_ALGORITHM=sha256

其中,‘token_data’是获取的user、role、endpoint、catlog等信息集合,而最重要的语句是cms使用签名生成token的过程:cms_sign_token,使用默认的sha256方式加密,处理过程使用process,进行数据的读取、处理,

process = subprocess.Popen(['openssl', 'cms', '-sign',

'-signer', signing_cert_file_name,

'-inkey', signing_key_file_name,

'-outform', 'PEM',

'-nosmimecap', '-nodetach',

'-nocerts', '-noattr',

'-md', message_digest, ],

stdin=subprocess.PIPE,

stdout=subprocess.PIPE,

stderr=subprocess.PIPE,

close_fds=True)

最后output, err = process.communicate(data) 生成Token-id,这个过程涉及到openssl相关的加密技术。

CMS token一般都超过1600个字节,样例:

(3)Fernet认证原理:

1.user在客户端输入用户名密码,发送给keystone。

2.Keystone验证用户名密码,并且生成token(UUID),发送给客户端。

3.客户端缓存token(UUID)

4.客户端发送具体的执行请求给openstack API

5、OpenStack API向 keystone请求token认证

6.Keystone从http请求中获取token,并检查token是否有效

7.Token有效,处理请求,并返回openstack api请求结果

8.Token失效,拒绝客户端请求,返回401。

当集群运行较长一段时间后,访问其 API 会变得奇慢无比,究其原因在于 Keystone 数据库存储了大量的 token 导致性能太差,解决的办法是经常清理 token。为了避免上述问题,社区提出了Fernet token,fernet 是当前主流推荐的token格式,它采用 cryptography 对称加密库(symmetric cryptography,加密密钥和解密密钥相同) 加密 token,具体由 AES-CBC 加密和散列函数 SHA256 签名。Fernet 是专为 API token 设计的一种轻量级安全消息格式,不需要存储于数据库,减少了磁盘的 IO,带来了一定的性能提升。为了提高安全性,需要采用 Key Rotation 更换密钥。

以上代码表明,token 包含了 user_id,project_id,domain_id,methods,expires_at 等信息,重要的是,它没有 service_catalog,所以 region 的数量并不影响它的大小。self.pack() 最终调用如下代码对上述信息加密:

该token 的大小一般在 200 多 Byte 左右,样例:

gAAAAABWfX8riU57aj0tkWdoIL6UdbViV-632pv0rw4zk9igCZXgC-sKwhVuVb-wyMVC9e5TFc 7uPfKwNlT6cnzLalb3Hj0K3bc1X9ZXhde9C2ghsSfVuudMhfR8rThNBnh55RzOB8YTyBnl9MoQ XBO5UIFvC7wLTh_2klihb6hKuUqB6Sj3i_8

简要叙述一下fernet采用 Key Rotation 更换密钥的原理,默认的轮换长度是3,当以keystone-manage fernet-setup生成密钥时,会看到0、1两个索引表征,这分别是什么意思呢?

在此,需要提一下三个概念:

primary key(主密钥)有且只有一个,名为为x,当前用于加密解密token

secondary key(次次密钥)有x-1个,从Primary退役下来的,用于解密当初它加密过的token

staged key(次密钥)有且只有一个,命名为0,准备下一个rotation时变为Primary key,可以解密token

那么上述0 表示的是staged key,1 表示的是primary key,

primary key相比较另外两种key,它的索引最高,并且可以加密、也可以解密;

staged key 相较于secondary key,它更有机会变为primary key。

AES256加密token,SHA256 HMAC验证完整性,

只要Keystone具有访问这些key的权限,token就不需要在keystone数据库中存储

fernet的数据性能最好,原因是它不需要后端持久化操作(采用 Key Rotation定期 更换密钥,只要Keystone具有访问这些key的权限,更新后的token就不需要在keystone数据库中存储,缓解了数据库负载压力),并且token的认证,使用的是密钥进行解密,能够直接得出token Data的信息,从而进行token的过期认证。它的失败原因,只可能是token过期了,或者是token放到了cache缓存中,但是已经被回收了。归根到底,还是token过期了。

keystone令牌三种生成方式的更多相关文章

  1. java的三种随机数生成方式

    随机数的产生在一些代码中很常用,也是我们必须要掌握的.而java中产生随机数的方法主要有三种: 第一种:new Random() 第二种:Math.random() 第三种:currentTimeMi ...

  2. hibernate笔记--继承映射关系的三种实现方式

    单表继承映射(一张表): 假设我们现在有三个类,关系如下: Person类有两个子类Student和Teacher,并且子类都具有自己独有的属性.这种实体关系在hibernate中可以使用单表的继承映 ...

  3. SP避免Form重复提交的三种方案

    SP避免Form重复提交的三种方案  1) javascript ,设置一个变量,只允许提交一次.   <script language="javascript">  ...

  4. 初学者易上手的SSH-hibernate02 三种查询方式

    在上一章中已经搭建好了一个hibernate的环境,那么这一章我们就使用这个环境来进行基本CRUD.在这之前我们先了解一个东西:主键生成策略.就是当向数据库表中插入记录的时候,这个记录的主键该如何生成 ...

  5. 【转】ABP webapi三种方式

    作者:圣杰 链接:https://www.jianshu.com/p/d14733432dc2 來源:简书 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 1. 引言 上一节我们 ...

  6. (转)理解Keystone的四种Token

    Token 是什么 通俗的讲,token 是用户的一种凭证,需拿正确的用户名/密码向 Keystone 申请才能得到.如果用户每次都采用用户名/密码访问 OpenStack API,容易泄露用户信息, ...

  7. nginx限流方案的实现(三种方式)

    通过查看nginx官方文档,小弟查看到了三种nginx限流方式. 1.limit_conn_zone 2.limit_req_zone 3.ngx_http_upstream_module 前两种只能 ...

  8. Secret的三种形式

    Secret ConfigMap这个资源对象是Kubernetes当中非常重要的一个对象,一般情况下ConfigMap是用来存储一些非安全的配置信息,如果涉及到一些安全相关的数据的话用ConfigMa ...

  9. 华为云计算IE面试笔记-FusionSphere Openstack有哪些关键组件,各组件主要功能是什么?三种存储接入组件的差异有哪些?

    1. Nova:在OpenStack环境中提供计算服务,负责计算实例(VM,云主机)生命周期的管理,包括生成.调度和回收.Nova不负责计算实例的告警上报(FC管). 2. Cinder:为计算实例提 ...

随机推荐

  1. 对html中iframe的研究

    虽然平时不怎么用iframe,但经常在网上听一些前辈说iframe怎样怎样,今天索性对iframe来个大研究,那样就不必去记那些条条框框了,自己体验一遍比看什么都好. 创建两个文件一个index.ht ...

  2. maven install 打包 报错 Cannot run program "gpg.exe": CreateProcess error

    打包报错, mvn install后加上参数-Dgpg.skip,例如:mvn install -Dgpg.skip   即可解决. 我们也可以去掉 这个 插件   <plugin>    ...

  3. php的explode()和implode()方法

    php 中,字符串与数组互转       拆分字符串 到数组 explode()    - -(其他语言中的 split) 将数组连接成字符串 implode() <?php $test = ' ...

  4. Oracle10g 64位 在Windows 2008 Server R2 中的安装 解决方案

    背景: 操作系统Windows 2008 Server R2 要安装Oracle10g 64位版本 安装时出现如下错误: 检查操作系统版本:必须是5.0,5.1,5.2 or 6.0.实际为6.1 未 ...

  5. java的classLoader分析与jettty的WebAppClassLoader

    classLoader,从名字就可以知道,用于加载class的东西. 我们知道在Java中,源文件是会被编译成class文件的,我们的程序的运行也是需要依赖这些编译成字节码的class文件,而这些字节 ...

  6. ActiveMQ P2P版的HelloWorld

    1.2 JMS应用程序接口 ConnectionFactory: 用户用来创建到JMS提供者的连接的被管对象.JMS客户通过可移植的接口访问连接,这样当下层的实现改变时,代码不需要进行修改. 管理员 ...

  7. MVC应用jQuery动态产生数据

    在前一篇<MVC应用程序JsonResult()的练习>http://www.cnblogs.com/insus/p/3402042.html中.Insus.NET在练习中学会了在视图中, ...

  8. MVC实现更新数据库的数据

    经过一系列MVC的练习,如数据库的数据显示,添加,删除等,还差一个功能,就是更新,那本次练习的是MVC对数据库的数据进行更新. 写好更新的存过程: 有了存储过程,可以写实体(Entity)的方法了.写 ...

  9. 使用JavaScript实现ajax

    实现ajax之前必须要创建一个 XMLHttpRequest 对象.如果不支持创建该对象的浏览器,则需要创建 ActiveXObject.具体方法如下: var xmlHttp;  function ...

  10. C# an error has occurred while updating the entries.see the log file

    message:An error occurred while updating the entries. See the inner exception for details. C# 在执行插入方 ...