Keystone 的四种 Token
四种 Token 的由来
D
版本时,仅有UUID
类型的Token
,UUID token
简单易用,却容易给Keystone
带来性能问题,从上图的步骤4
可看出,每当OpenStack API
收到用户请求,都需要向Keystone
验证该token
是否有效。随着集群规模的扩大,Keystone
需处理大量验证token
的请求,在高并发下容易出现性能问题。- 于是
PKI(Public Key Infrastructrue) token
在G
版本运用而生,和UUID
相比,PKI token
携带更多用户信息的同时还附上了数字签名,以支持本地认证,从而避免了步骤 4。 因为PKI token
携带了更多的信息,这些信息就包括service catalog
,随着OpenStack
的Region
数增多,service catalog
携带的endpoint
数量越多,PKI token
也相应增大,很容易超出HTTP Server
允许的最大HTTP Header
(默认为 8 KB),导致HTTP
请求失败。 PKIZ token
就是PKI token
的压缩版,但压缩效果有限,无法良好的处理token size
过大问题。- 前三种
token
都会持久性存于数据库,与日俱增积累的大量token
引起数据库性能下降,所以用户需经常清理数据库的token
。为了避免该问题,社区提出了Fernet token
,它携带了少量的用户信息,大小约为255 Byte
,采用了对称加密,无需存于数据库中。
UUID
UUID token
是长度固定为 32 Byte 的随机字符串,由uuid.uuid4().hex
生成。- 但是因
UUID token
不携带其它信息,OpenStack API
收到该token
后,既不能判断该token
是否有效,更无法得知该token
携带的用户信息,所以需经图一步骤 4 向Keystone
校验token
,并获用户相关的信息。 UUID token
简单美观,不携带其它信息,因此Keystone
必须实现token
的存储和认证,随着集群的规模增大,Keystone
将成为性能瓶颈。
PKI
PKI
的本质就是基于数字签名,Keystone
用私钥对token_data
进行数字签名生成token
,各个API server
用公钥在本地验证该token
。- 各个
API server
解开token
后就可以拿到用户相关信息。token_data
如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28{
"token": {
"methods": [ "password" ],
"roles": [{"id": "5642056d336b4c2a894882425ce22a86", "name": "admin"}],
"expires_at": "2015-12-25T09:57:28.404275Z",
"project": {
"domain": { "id": "default", "name": "Default"},
"id": "144d8a99a42447379ac37f78bf0ef608", "name": "admin"},
"catalog": [
{
"endpoints": [
{
"region_id": "RegionOne",
"url": "http://controller:5000/v2.0",
"region": "RegionOne",
"interface": "public",
"id": "3837de623efd4af799e050d4d8d1f307"
},
......
]}],
"extras": {},
"user": {
"domain": {"id": "default", "name": "Default"},
"id": "1552d60a042e4a2caa07ea7ae6aa2f09", "name": "admin"},
"audit_ids": ["ZCvZW2TtTgiaAsVA8qmc3A"],
"issued_at": "2015-12-25T08:57:28.404304Z"
}
}PKIZ
PKIZ
在PKI
的基础上做了压缩处理,但是压缩的效果极其有限,一般情况下,压缩后的大小为PKI token
的90 %
左右,所以PKIZ
不能友好的解决token size
太大问题。
Fernet
- 用户可能会碰上这么一个问题,当集群运行较长一段时间后,访问其
API
会变得奇慢无比,究其原因在于Keystone
数据库存储了大量的token
导致性能太差,解决的办法是经常清理token
。 - 为了避免上述问题,社区提出了
Fernet token
,它采用对称加的方式加密token_data
。 Fernet
是专为API token
设计的一种轻量级安全消息格式,不需要存储于数据库,减少了磁盘的IO
,带来了一定的性能提升。为了提高安全性,需要采用Key Rotation
更换密钥。
总结
Token 类型 | UUID | PKI | PKIZ | Fernet |
---|---|---|---|---|
大小 | 32 Byte | KB 级别 | KB 级别 | 约 255 Byte |
支持本地认证 | 不支持 | 支持 | 支持 | 不支持 |
Keystone 负载 | 大 | 小 | 小 | 大 |
存储于数据库 | 是 | 是 | 是 | 否 |
携带信息 | 无 | user、catalog 等 | user、catalog 等 | user 等 |
涉及加密方式 | 无 | 非对称加密 | 非对称加密 | 对称加密(AES) |
是否压缩 | 否 | 否 | 是 | 否 |
版本支持 | D | G | J | K |
如何选择 Token
Token
类型的选择涉及多个因素,包括 Keystone server
的负载、region
数量、安全因素、维护成本以及 token
本身的成熟度。region
的数量影响 PKI/PKIZ token
的大小,从安全的角度上看,UUID
无需维护密钥,PKI
需要妥善保管 Keystone server
上的私钥,Fernet
需要周期性的更换密钥,因此从安全、维护成本和成熟度上看,UUID > PKI/PKIZ > Fernet
如果:
- Keystone 负载低,region 少于 3 个,采用 UUID token。
- Keystone 负载高,region 少于 3 个,采用 PKI/PKIZ token。
- Keystone 负载低,region 大与或等于 3 个,采用 UUID token。
- Keystone 负载高,region 大于或等于 3 个,K 版本及以上可考虑采用 Fernet token。
Keystone 的四种 Token
http://mybestcheng.site/2022/11/20/openstack/keystone/keystone-token/