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"
 }
 }PKIZPKIZ在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/