Ceph認證的三層含義(上)
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) 組件和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也確實是這么實現的。
第一階段:認證用戶 第二階段:獲取service服務的ticket
4.2.1 第一階段—認證用戶
說到認證用戶,第一個想到的就是keyring,先簡單聊一下keyring
4.2.1.1 訪問鑰匙
Ceph在使用中,如果我們開啟了Cephx會有很多keyring,一個keyring類似如下:
client.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)
當我們運行如下類似命令的時候生成
# ceph auth add xxx xxx
- 存在哪里(where)
ceph auth命令最后發給mon,存在了mon的rocksdb中。
- 誰會使用(who)
這個keyring誰會使用,主要大致有以下兩類:
客戶端: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)傳過來,比特位代表如下
#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。
