keystone支持多种令牌(token)生成方式,主要包括 UUID、PKI 和 Fernet 三种。
一.UUID

- OpenStack 平台dashboard 通过restapi 调用keystone,首次携带用户的用户名和密码,keystone验证通过后生成UUID token,存储在keystone数据库中,然后把这个UUID 发给客户端;
- 客户端调用nova-api 创建虚拟机;
- nova-api 先发送到keyStone,等待keyStone验证token ;
4.keystone 从请求中获取UUID,再从keystone数据库中获取UUID,过期时间,两者进行比较和验证;
5.keystone 验证完毕后,返回给nova 服务,nova服务进行后续创建vm 流程;
从上述的流程中可以看出,用户的每个请求都需要通过keystone服务在线进行验证,如果存在成千上万个虚拟机创建,网卡创建,keystone流量会激增,后端的查询会造成性能瓶颈;
二.PKI
PKI 是利用公钥密码理论技术为各服务以及网络安全领域提供安全服务的基础设施。

- keystone 服务生成CA公钥和私钥,CA作为权威机构,用来为用户做证书签名认证,证明是该用户身份,防止身份伪造;
openssl genrsa -out ca.key.pem 4096 (CA 生成 RSA 私钥文件,公钥信息是放在ca.key.pem私钥文件中,可以从ca.key.pem 提取公钥信息,在实际环境中,通常一般不进行公钥信息提取,而是使用CA证书,CA证书包含了公钥信息且被签名更可靠,这里使用单层次根证书为例)
-----BEGIN RSA PRIVATE KEY-----
MIIJKQIBAAKCAgEApdXUdhGn/i3bwaWWP8ZQhAH1nlk/8lfQ//KwebGHBklnxZNR
IaYZD0mKUTDyKvpMYnzsG/enO2w10uwAWUx3cQJLmCBfI0vlVBObRh0F67f5QC1S
CGov2g+ijoS7HTXtW8sV2d313mn6cZmrH32aNQSRYeNt7ZWLaLpaIMNki9PjrB5g
KBL75jCgxgA+IpQxCeXd2gpjUGM1HZHik7A8S2v3cPna0WD0vg3RLoKir2pCmxQV
kPBvdUao1ui6QrnlG91bIed5cP+fyO96Z/Y4WogMmpDhbxm7tNWVVFM5CZfFfyGj
GgL0nRe3j5lLmc8YENByRYs05VNryuQsN0n9NODWXNbEYW.
-----END RSA PRIVATE KEY-----
提取公钥信息如下: openssl rsa -in ca.key.pem -pubout -out ca_public.key
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApdXUdhGn/i3bwaWWP8ZQ
hAH1nlk/8lfQ//KwebGHBklnxZNRIaYZD0mKUTDyKvpMYnzsG/enO2w10uwAWUx3
cQJLmCBfI0vlVBObRh0F67f5QC1SCGov2g+ijoS7HTXtW8sV2d313mn6cZmrH32a
NQSRYeNt7ZWLaLpaIMNki9PjrB5gKBL75jCgxgA+IpQxCeXd2gpjUGM1HZHik7A8
S2v3cPna0WD0vg3RLoKir2pCmxQVkPBvdUao1ui6QrnlG91bIed5cP+fyO96Z/Y4
WogMmpDhbxm7tNWVVFM5CZfFfyGjGgL0nRe3j5lLmc8YENByRYs05VNryuQsN0n9
NODWXNbEYW2v4Rvi3RI7BnOkMoVsSDdFNjmmB67KnVz3HAfnBgBA655J+yCr945D
5J9ghq0dk9t0fP+AM1F3G8SI1ShmjXBuR7RjhdBFVWU5tu9en//Vd5GjP4yQBzFa
Aq1oks0VrihZHD6nTdgtDT/mNlBGISBUXAcYkV7ygl56SsUb6n7aylMjD0ss3D9D
47DfTiCP8O19DMD5PsUviHiZbWTbdMhxtmLpxRHgeZ9CYk6j7b7+yTGalPA9Dto7
mPJIMBFN+5LPs9N8oa7UKKw2RpMAAZfQb/KaSRs/fGIJPFe0p8CELe/UWgFH8w2b
hqQY6ml8VPDxJymR3vG2HccCAwEAAQ==
-----END PUBLIC KEY-----
openssl req -new -x509 -key ca.key.pem -out ca.crt.pem -days 3650 (生成CA 证书ca.crt.pem,包含CA公钥,身份信息以及CA签名)
- keystone 服务 生成keystone 公钥和私钥;
openssl genrsa -out signing_key.pem 2048 (生成keystone 私钥文件signing_key.pem,同时该文件也包含keystone 公钥信息)
openssl req -new -key signing_key.pem -out signing_cert.csr (使用keystone 私钥signing_key.pem创建一个CSR证书签名请求signing_cert.csr,里面包含keystone 公钥和身份信息)
openssl x509 -req -in signing_cert.csr -CA ca.crt.pem -CAkey ca.key.pem -out signing_cert.pem -days 365(使用CA私钥 ca.key.pem 和CA 证书ca.crt.pem 为 signing_cert.csr 进行签名,生成一个有效期为365天的证书)
3.将CA证书文件ca.crt.pem 和 keystone 证书文件signing_cert.csr 发送到其他服务节点
4.用户携带用户名,密码等参数向keystone 发送授权认证请求
5.keystone 验证用户的用户名密码(首次验证会从keystone db中获取存储的用户名,密码比对验证)
6.keystone 验证通过后,生成Token 数据(包含token 有效期,用户名,用户角色等),然后针对Token 数据 计算hash 值,生成摘要,使用keystone私钥进行数字签名
7.返回PKI Token给用户 (原始的Token 数据以及数字签名)
8.后续用户携带PKI Token,请求nova 创建组件
- nova 服务进行keystone证书验证(验证是否由可信CA发布,证书是否在有效期内,证书是否被吊销)
10.nova 进行数字签名验证,从PKI Token 分离出原始的token 信息以及对摘要计算的签名信息,首先对原始的token 信息计算摘要hash值,然后利用本地的keystone 公钥对数字签名信息进行解密,得到解密后的摘要hash值,如果两个摘要信息的hash值一致,则验证通过,说明token 内容信息未被篡改和伪造。 这里因为有CA对keystone 私钥的签名认证,可以保证keystone 的一对公私钥文件未被中间人随意篡改,本地存储的keystone 证书就是由keystone 服务所生成的
11.nova 对这个合法的token 进行有效期验证,验证通过后,提取用户id,角色列表权限,处理接下来的逻辑
12.完成之后,返回response 响应给用户
三.Fernet
Fernet是一种对称加密的令牌,由keystone生成, 其他服务节点可以在本地进行验证,无中心化存储,无需每次都请求keystone。

生成Token以及验证
1.keystone 生成初始密钥对
keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone
/etc/keystone/fernet-keys:
总用量 8
drwx------ 2 keystone keystone 24 9月 28 08:17 .
drwxr-x--- 4 root keystone 200 11月 9 14:28 ..
-rw------- 1 keystone keystone 44 9月 28 08:17 0
-rw------- 1 keystone keystone 44 9月 28 08:17 1
2.用户发送认证请求
3.keystone 对用户名密码进行验证
4.验证通过后通过/etc/keystone/fernet-keys 获取密钥库
5.此时构建token json数据并使用主密钥进行加密(0号密钥)
6.返回Token 给用户
7.用户携带Token 调用 api 请求nova
8.nova获取所有有效密钥(0号和1号密钥, 0号密钥用于生成新Token,1号密钥用于验证旧Token)
9.nova 使用解密密钥验证Token
10.nova 验证Token有效期和内容
11.返回响应给用户
Fernet密钥管理机制
keystone-manage fernet_route ,通过密钥的定期轮换,可以保证Token 安全性,旧的 Token 在二级密钥被丢弃后自动失效。