1. 背景
Ceph是分布式存储系统,允许多用户同时访问,为了保证访问的安全性,需要提供一套认证系统来对用户进行认证。Ceph采用了Kerberos认证设计思想。
2. Kerberos
Kerberos是一种计算机网络认证协议,它允许某实体在非安全网络环境下通信,向另一个实体以一种安全的方式证明自己的身份。
这个协议主要分为三部分
- Key Distribution Center(KDC):认证中心以及分发ticket
- Client:客户端
- Service:客户端想要访问的服务
理论很复杂,简单的讲就是
- Client带着认证信息去KDC进行认证
- 认证通过,从ticket server获取service X服务的ticket-x
- Client使用ticket-x去访问service X服务
tips: Kerberos用户认证的一个核心就是客户端用一个secret加密,服务端能解密出来就算认证成功。
3. 从Kerberos到Ceph
Ceph认证就是实现了Kerberos,首先把Ceph组件也进行三种组件分类
- KDC:monitor
- Client:radosclient、ceph-fuse
- Service:MDS、OSD、MGR
大体流程跟上面Kerberos一样,多了service服务到monitor获取service secret,这个是从Kerberos依葫芦画瓢想到的,其实Ceph里面“Client”是一个范指,主要包含monclient模块的都可以称为“client”,比如OSD、MDS、MGR都包含monclient,从这个角度讲它们也属于“Client”,比如以OSD作为“Client”如下示意
下面来细说一下Ceph
4. Ceph的实现
为了方便理解我把Ceph认证分成三层含义(非kerberos原理):1
2
3(1) 组件和monitor的连接认证
(2) 用户认证
(3) 除monitor之外其他组件的连接认证
4.1 组件和monitor之间的连接认证
Ceph在tcp三次握手之上又加了一层自定义的网络连接协议,主要用来确认一些信息,比如banner,客户端的ip和端口,auth认证等
只有auth认证通过之后,Ceph连接才算建立完成,后面就可以用于消息发送。然而不同组件之间连接的auth认证行为不一样。这里先讨论组件和monitor之间的连接认证。client和其他组件跟monitor通信都是无条件通过。
我们可能好奇为什么这边会无条件认证,按理认证不应该进行用户身份的认证吗,而需要用户认证则需要在建立好的Ceph连接上发送MAuth消息,而现在Ceph连接都还没建立,根本无从认证,如果这里不设置无条件通过,就会出现鸡和蛋问题。
4.2 用户认证
用户认证是包含monclient模块的“Client”跟mon建立连接之后通过authenticate发送MAuth消息来认证用户
从kerberos可以看出用户认证的时候分为两个阶段发了两次请求,Ceph也确实是这么实现的。1
2第一阶段:认证用户
第二阶段:获取service服务的ticket
4.2.1 第一阶段–认证用户
说到认证用户,第一个想到的就是keyring,先简单聊一下keyring
4.2.1.1 访问钥匙
Ceph在使用中,如果我们开启了Cephx会有很多keyring,一个keyring类似如下:1
2
3
4
5
6client.admin
key: AQBPWeZhTnH6FhAAd6hoo1oMkw3/G4teWXwKAA==
caps: [mds] allow *
caps: [mgr] allow *
caps: [mon] allow *
caps: [osd] allow *
这是一个admin用户的keyring,可以看到keyring内容主要包含两类: 一类是key,一类是caps,其中的key是一个secret,主要用来加密,caps是用户对于各个服务的访问权限。来一个灵魂四拷问:when、where、who、how
- 何时生成(when)
当我们运行如下类似命令的时候生成1
# ceph auth add xxx xxx
- 存在哪里(where)
ceph auth命令最后发给mon,存在了mon的rocksdb中。
- 谁会使用(who)
这个keyring谁会使用,主要大致有以下两类:1
2客户端:radosclient、ceph-fuse
组件服务:osd、mgr、mds
这些都会包含一个monclient
- 怎么使用(how)
在客户端或者组件服务启动时,通过包含的monclient进行认证。
Kerberos认证的核心就是客户端使用秘钥对消息进行加密,如果KDC能通过秘钥进行解密成功就认证通过。Ceph有点不一样,Ceph使用keyring中的key以及其他的东西(challenge)在monclient和monitor分别算出一个key,进行匹配是不是相同,相同则认证通过,反正。
4.2.1.2 计算匹配
匹配通过就算认证用户ok
4.2.2 第二阶段–获取service Ticket
在发送client challenge请求的时候,也会把客户端想要访问组件以bit的方式(want_key)传过来,比特位代表如下1
2
3
4
5
6#define CEPH_ENTITY_TYPE_MON 0x01
#define CEPH_ENTITY_TYPE_MDS 0x02
#define CEPH_ENTITY_TYPE_OSD 0x04
#define CEPH_ENTITY_TYPE_CLIENT 0x08
#define CEPH_ENTITY_TYPE_MGR 0x10
#define CEPH_ENTITY_TYPE_AUTH 0x20
比如客户端会和MDS和OSD访问,则需要设置want_keys为6
4.3 除monitor之外其他组件的连接认证
有了service ticket,除montior之外其他组件就可以进行连接认证,如下
这里从monitor除了获取service ticket,还返回了session key,这个session key在下面验证的时候会用到。
4.3.1 验证方法
这里的连接认证方法和用户认证不一样,不是通过计算key来比对,而是通过加密解密来完成,大致思路就是monitor发送给客户端的service ticket是用一个service_secret进行了加密,而客户端会在加上一些其他的信息(比如nonce)通过session key加密然后和ticket一起发送给连接的另一端。
认证的大体思路是这样,那这里recv端的service secret是哪里来的?
4.3.2 service secret
service secret是用来加密service ticket的,monitor发送给客户端的ticket就已经加密好,所以service secret是monitor那边生成的,service服务组件获取service secret是在所包含的monclient模块用户认证完成之后从monitor取回属于自己service服务的service secret。
至此认证的大体流程框架介绍完,其他细节敬请期待~~