Fernet Token in Keystone v3 (by quqi99)

原创 2016年08月30日 21:20:45

**作者:张华 发表于:2016-08-11
版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明
( http://blog.csdn.net/quqi99 )**

问题的由来

keystone中使用token的过程
- UUID: nova client通过user/pass从keystone获取UUID Token(UUID为一段32位字符串),nova client还得再拿UUID去keystone端验证token是否有效(有效期,用户组,服务目录等元数据信息存储在DB中),这样keystone的压力很大,另外由于需要持久化token所以token在不同region之间同步也是一个问题。
- PKI: client通过user/pass从keystone获取PKI Token(包括了元数据信息, keystone会只用私钥对其进行签名和CMS编码,没有加密),nova client不需要再去keystone端验证, nova能直接解码得到token的有效性等元数据信息,故nova不需要再请求keystone来验证这个Token,它省略了上图中的步骤4能大大减轻keystone的压力。但缺点是它的长度容易超过WEB Server对HTTP HEADER长度的限制, 且同样需要持久化token。
- PZKI: PKI的长度容易超过WEB Server对HTTP HEADER长度的限制,于是PZKI通过zlib来对token进行压缩。它只解决了token过长的问题,仍然没有解决持久化token带来的问题。
- Fernet: fernet使用AES-CBC来对称加密并使用SHA256来签名token,token只能通过对称密钥读取和更改,不需要持久化token,对于多个keystone节点的region之间的部署,只需要将相同的key发布到所有节点上,那么无论是通过哪个节点生成的token,都可以被其他的keystone节点所验证。用户在部署时所要考虑的,就是如何在Fernet Key Rotate的时候保持所有节点上key repository的同步,而这远远要比同步上万条token纪录来的简单。且fernet token只加密必要的信息,长度一般不超过255字节,避免了PKI token过大的问题。

Fernet Key Format

Fernet Key是由下列字段组合的base64编码(base64.urlsafe_b64encode):

  • 8 bits, Fernet Format Version(0x80)
  • 64 bits, current timestamp, int(time.time())
  • 128 bits, Initailization Vector(IV), os.urandom(16)
  • Ciphertext(Version, User_ID, Methods, Project_ID, Expiration Time, Audit IDs)
  • 256 bits, SHA256 HMAC with signing key

Fernet Key Rotation

可以通过max_active_keys=3配置在/etc/keystone/fernet-keys目录生成至多3个key, 数字最大的叫Primary Key, 其次大的叫Secondary Key, 再其次大的叫Staged Key。keystone使用Primary Key加密,可使用所有的Key按2,1,0的顺序进行解密和验证。

  • 默认使用keystone-manage utility初始化/etc/keystone/fernet-keys目录时,1为Primar Key, 0为Stage Key,没有Secondary Key.
  • Fernet Key Rotation后,以前的0变成2成为Primary Key, 以前的1还是1作为Secondary Key, 新生成0作为Staged Key
  • 再次Fernet Key Rotation后,0 becomes 3, 1 gets deleted, 2 stays 2, a new key becomes 0
  • 两个region不需要同时进行Fernet Key Rotation, 因为keystone使用Primary Key加密,使用所有的Key按2,1,0的顺序进行解密和验证。不需要sync token,但是需要sync token repository, 这样就能使一个node生成的tokens可以立即被其他节点验证。

快速测试

1, 采用juju快速部署测试环境:

$ juju-deployer -c ./keystone-v3.yaml -d xenial-mitaka
$ cat keystone-v3.yaml
keystone-v3:
  services:
    keystone:
      branch: https://github.com/openstack/charm-keystone
      num_units: 1
      options:
        preferred-api-version: 3
        admin-password: 'password'
        admin-token: 'ubuntutesting'
        debug: 'true'
        verbose: 'true'
    mysql:
      branch: https://github.com/openstack/charm-percona-cluster
      constraints: mem=1G
      num_units: 1
      options:
        dataset-size: '50%'
        root-password: 'password'
        sst-password: 'password'
  relations:
    - [ keystone, mysql ]
xenial-mitaka:
  inherits: keystone-v3
  series: xenial

2, 更新keystone.conf

[token]
#provider = keystone.token.providers.uuid.Provider
provider = fernet

3, 更新DB

su -s /bin/sh -c "keystone-manage db_sync" keystone

4, Initiate fernet key repository

mkdir -p /etc/keystone/fernet-keys
chown -R keystone:keystone /etc/keystone/fernet-keys
keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone

5, restart apache2

cat /etc/apache2/sites-enabled/wsgi-keystone.conf
systemctl restart apache2

6, Verify

export OS_TOKEN=ubuntutesting
export OS_URL=${OS_AUTH_PROTOCOL:-http}://`juju-deployer -f keystone`:5000/v3
export OS_IDENTITY_API_VERSION=3

openstack service create --name keystone --description "OpenStack Identity" identity
openstack service list

openstack endpoint create --region RegionOne identity public http://`juju-deployer -f keystone`:5000/v3
openstack endpoint create --region RegionOne identity internal http://`juju-deployer -f keystone`:5000/v3
openstack endpoint create --region RegionOne identity admin http://`juju-deployer -f keystone`:35357/v3
openstack endpoint list

openstack domain create --description "Default Domain" default
openstack domain list

openstack project create --domain default --description "Admin Project" admin
openstack project create --domain default --description "Service Project" services
openstack project list

openstack role create admin
openstack role create user
openstack role list

openstack user create --domain default --password-prompt admin
openstack role add --project admin --user admin admin
openstack user create --domain default --password-prompt demo
openstack role add --project services --user demo user
openstack user list

#Verify Token
cat > demo-openrc << OFF
export OS_PROJECT_DOMAIN_NAME=default
export OS_USER_DOMAIN_NAME=default
export OS_PROJECT_NAME=services
export OS_USERNAME=demo
export OS_PASSWORD=password
export OS_AUTH_URL=http://`juju-deployer -f keystone`:5000/v3
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2
OFF
source ./demo-openrc
unset OS_TOKEN OS_URL
openstack token issue

#Get Token
cat > token-request.json << OFF
{
  "auth": {
    "identity": {
      "methods": [
        "password"
      ],
      "password": {
        "user": {
          "domain": {
            "name": "default"
          },
          "name": "demo",
          "password": "password"
        }
      }
    }
  }
}
OFF
USER_ID=$(curl -d @token-request.json -H "Content-type: application/json" http://`juju-deployer -f keystone`:5000/v3/auth/tokens | python -c "import sys; import json; tok = json.loads(sys.stdin.read()); print tok['token']['user']['id'];")

TOKEN=$(curl -i -d @token-request.json -H "Content-type: application/json" http://`juju-deployer -f keystone`:5000/v3/auth/tokens |grep X-Subject-Token |awk -F ':' '{print $2}') 

#Use Token
curl -H "X-Auth-Token: $TOKEN" http://`juju-deployer -f keystone`:5000/v2.0/tenants

Fernet Key in Multiple Regions

Fernet Key in multiple regions
1, 需要创建第二个keystone作为RegionTwo

openstack endpoint create \
--publicurl http://controller:5000/v2.0 \
--internalurl http://controller:5000/v2.0 \
--adminurl http://controller:35357/v2.0 \
--region RegionTwo \
identity

2, 这些Keystone Region Nodes所使用的DB应该sync
3, 上面fernet_setup命令生成的fernet key初始时应该复制到所有Keystone region nodes.
4, Key rotate

keystone-manage fernet_rotate --keystone-user keystone --keystone-group keystone
ls /etc/keystone/fernet-keys/

Key Rotation
5, token不需要sync,但fernet key repository应该在所有keystone region nodes间作sync。例:

rsync -e 'ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' \
          -avz \
          --delete \
          {{ keystone_fernet_tokens_key_repository }}/ \
          {{ keystone_system_user_name }}@{{ hostvars[host]['ansible_ssh_host'] }}:{{ keystone_fernet_tokens_key_repository }}/

Appendix - Keystone v3

  1. configurations`[service_credentials]
    auth_url = http://xxxx:5000/v3
    username = ceilometer
    tenant_name = service
    password = xxxxxx
    project_name = service
    project_domain_name = default
    user_domain_name = default
    auth_type = password

[keystone_authtoken]
auth_plugin = password
auth_url = http://192.168.200.178:35357
auth_uri=http://192.168.200.178:5000
username = ceilometer
password = xxxxx
project_name = services
user_domain_name = default
project_domain_name = default
2. env variables

export OS_PROJECT_DOMAIN_NAME=default
export OS_USER_DOMAIN_NAME=default
export OS_AUTH_URL=http://[2001:2:3:4500:fa32:e4ff:febe:87cd]:5000/v3
export OS_PROJECT_NAME=services
export OS_USERNAME=demo
export OS_PASSWORD=password
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2
3.
from keystoneauth1.identity import v3
from keystoneauth1 import session
from keystoneclient.v3 import client
auth = v3.Password(auth_url=’http://10.5.8.27:5000/v3‘,
username=’ceilometer’,
password=’xxx’,
project_name=’services’,
user_domain_name=’default’,
project_domain_name=’default’)
sess = session.Session(auth=auth)
keystone = client.Client(session=sess)
tenants = keystone.projects.list()
4.
TOKEN=$(curl -i -H “Content-Type: application/json” -d ’
{ “auth”: {
“identity”: {
“methods”: [“password”],
“password”: {
“user”: {
“name”: “ceilometer”,
“domain”: { “name”: “default” },
“password”: “xxx”
}
}
}
}
}’ http://10.5.8.27:5000/v3/auth/tokens |grep X-Subject-Token |awk -F ‘:’ ‘{print $2}’)
curl -g -X GET http://10.5.8.27:35357/v3/auth/projects -H “Accept: application/json” -H “X-Auth-Token: $TOKEN” | python -m json.tool
5.
openstack domain list –os-identity-api-version 3 –os-token ubuntutesting –os-url http://10.5.7.210:35357/v3
openstack token issue –os-username ceilometer –os-project-name services –os-auth-url http://10.5.7.210:5000/v3 –os-password xxx –os-user-domain-name default –os-project-domain-name default
`

参考

[1] https://developer.ibm.com/opentech/2015/11/11/deep-dive-keystone-fernet-tokens
[2] http://blog.csdn.net/zjluobing/article/details/51492356
[3] http://dolphm.com/inside-openstack-keystone-fernet-token-payloads/
[4] https://github.com/openstack/openstack-ansible-os_keystone/blob/master/templates/keystone-fernet-rotate.sh.j2
[5] http://gogosatellite.blogspot.jp/2016/05/openstack-keystone-fernet-key-in.html
[6] https://bugs.launchpad.net/keystone/+bug/1338550

版权声明:本文为博主原创文章,如需转载,请注明出处!

Linux内核模块简介

一. 摘要 这篇文章主要介绍了Linux内核模块的相关概念,以及简单的模块开发过程。主要从模块开发中的常用指令、内核模块程序的结构、模块使用计数以及模块的编译等角度对内核模块进行介绍。在Linux系...

openstack neutron学习(一) ---- neutron-server入口

参考资料 一篇比较早的blog,讲解nova-network的,但是原理一样。 《OpenStack云平台的网络模式及其工作机制》 http://blog.csdn.net/hilyoo/arti...
  • llg8212
  • llg8212
  • 2014年01月13日 16:06
  • 4165

修复一个bug基于grizzly版本在同一台节点上运行多个l3-agent支持多个公网段(by quqi99)

作者:张华  发表于:2014-07-25版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明(http://blog.csdn.net/quqi99 )...
  • quqi99
  • quqi99
  • 2014年07月25日 15:12
  • 2483

Neutron中的L3 HA特性(by quqi99)

作者:张华  发表于:2014-01-26 版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 ( http://blog.csdn.net/quqi99 ...

Gcov单元测试覆盖率 ( by quqi99 )

                                                                                 Gcov单元测试覆盖率( by...
  • quqi99
  • quqi99
  • 2012年08月29日 15:08
  • 4293

使用免费的类似于花生壳的动态DNS服务访问家中内网机器(by quqi99)

家里的ip是内网地址,adsl路由器上的公网ip是变化的,所以有花生壳之类的程序来提供动态dns解析功能(它提供一个二级域名,同时硬件路由器在公网ip变动之后向它的dns解析器更新,同时硬件路由器应该...
  • quqi99
  • quqi99
  • 2014年05月05日 22:27
  • 7611

定制你自己的Linux系统 ( by quqi99 )

定制你自己的Linux ( by quqi99 ) 作者:张华  发表于:2013-09-21 版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 ( http...
  • quqi99
  • quqi99
  • 2013年09月21日 09:26
  • 8685

一种Neutron部署拓扑 (by quqi99)

作者:张华  发表于:2014-03-04 版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 (http://blog.csdn.net/quqi99 )...

Tomcat集群配置笔记 ( by quqi99 )

Tomcat集群配置笔记 ( by quqi99 )
  • quqi99
  • quqi99
  • 2011年04月07日 15:46
  • 6525

Fedora 16上源码建立pydev + eclipse的OpenStack开发环境笔记草稿 ( by quqi99 )

Fedora 16上源码建立pydev + eclipse的OpenStack开发环境笔记草稿  ( by quqi99 ) 作者:张华  发表于:2012-3-30 版权声明:可以任意转载,...
  • quqi99
  • quqi99
  • 2012年03月30日 13:49
  • 9211
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Fernet Token in Keystone v3 (by quqi99)
举报原因:
原因补充:

(最多只允许输入30个字)