Ceph X protocol
Ceph的Auth认证服务由MON中的AuthMonitor模块提供,随MON启动而启动。启动时会检查认证服务是否为cephx,如果是将加载admin.keyring(里面包含客户端服务器共享的密钥)。
当服务器接受请求后会开启一个会话,并初始化一个server_challenge,该值会传输给请求授权的客户端。客户端接收到server_challenge后,首先判断该CEPHX client是否为第一次生成,若是(starting为true),则进入以下语句
首先解码数据,获取其中的server_challenge并打印。
然后验证是否有对请求中所有操作的服务权限,即validate_ticket,ticket包含对每个服务的操作权限及handler,每个服务的handler都对应一个值,用与或算法来确定客户端有那些服务的handler,需要那些服务的handler,缺少哪些服务的handler,每个服务 handler对应的16进制值如下表所示
如果已经有AUTH(32)的handler,缺少OSD(4)和MON(1)的handler,则开启debug_auth后提示的信息将会是
最后返回-EAGAIN,控制权交由MonClient(voidMonClient::handle_auth(MAuthReply *m))
MONClient将根据所需的服务handler创建不同request,创建过程中会随机生成一个client_challenge加上接收到的server_challenge,加密服务的secret到req.key中,然后通过encode加密到待传输给服务器的字节流中。
判断是否有need的服务,如果有,就创建authorizer请求Auth服务器获取到对应服务的tickets。
其中challenge机制就是确保客户端和服务器保存的keyring完全一致,具体流程如下:
challenge:用来验证客户端和服务器之间的服务(entry)的密钥(key)是否一致,不一致就会返回-EPERM无权限的提示。key值示例:
Ticket:一个记录,客户用它来向服务器证明自己的身份,包括客户标识、会话密钥、时间戳。
首先,客户端必须与认证器进行身份认证。其中将会用到共享密钥机制,协商过程如下
1.获取principal/Auth的session key
(认证请求)
客户端->认证器:发送内容principal,principal_addr
...认证器在数据库中查询信息...
认证器->客户端:
A:由principal_secret 加密的{principal/auth session key,validaty}
B:由authsecret加密的{principal ticket, validity, principal/auth session key}
A,B的数据结构为:
认证器的pricipal_secret在auth/cephx/CephxServiceHandler.cc line 99获取,存放在eauth.key中
然后在line 146行中加密信息并构建信息:
客户端的principal_secret由auth/cephx/CephxClientHandler.ccline 120获取
然后通过函数verify_service_ticket_reply(),若解析成功,则获取相关服务的handler
authsecret由generate_secret(info.session_key)生成
其中服务对应的ticket通过函数build_authorizer()生成
如果成功,客户端上将有principal/auth的session key。下一步是请求授权使用其他一些服务
2. 获取principal/service的session key
客户端->认证器:B,由principal/authsession key加密的{principal_addr, timestamp}
认证器->客户端:
E:由svcsecret加密的{serviceticket}
F:由principal/authsession key加密的{principal/service session key, validity}
principal_addr, timestamp = authenticator
其中service ticket的内容为principalname, client network address, validity, principal/service session key
注意:步骤1和步骤二有大量相似的内容:连接认证器并向其请求一个key
做完这步后,客户端需要有principal/servicesession key,用来后续的创建会话
3.在服务器打开一个会话
客户端->服务器:E+由principal/servicesession key加密的{principal_addr, timestamp}
服务器->客户端:由principal/service/sessionkey加密的{timestamp+1}
timestamp+1 = reply authenticator
此时,服务器完全授权与客户端。从逻辑上来说这里主要有两个操作。第一个操作就是从服务器获取一个session key(步骤一和步骤二),第二个操作为向服务器发送ticket进行认证
认证一次的客户端LOG:
2017-06-07 02:13:01.623684 7fcebee53700 10 In get_auth_session_handler for protocol 0 2017-06-07 02:13:01.624411 7fcebcf03700 10 cephx server client.admin: start_session server_challenge 74bce2b1ff1d53cf 2017-06-07 02:13:01.625707 7fcebcf03700 10 cephx server client.admin: handle_request get_auth_session_key for client.admin 2017-06-07 02:13:01.625755 7fcebcf03700 20 cephx server client.admin: checking key: req.key=9f181d3f0a65f5d6 expected_key=9f181d3f0a65f5d6 2017-06-07 02:13:01.625826 7fcebcf03700 30 cephx keyserverdata: get_service_secret service auth id 10 AQAaQjZZu5S9MhAABm5KJtxKnRixsZ59P/VyLw== expires 2017-06-07 05:48:10.851268 2017-06-07 02:13:01.625845 7fcebcf03700 10 cephx: build_service_ticket_reply encoding 1 tickets with secret AQAK/DBZI7nTCBAAR9jeJ21LPvMjpd8NsP036Q== 2017-06-07 02:13:01.625878 7fcebcf03700 10 cephx: build_service_ticket service auth secret_id 10 ticket_info.ticket.name=client.admin 2017-06-07 02:13:01.625916 7fcebcf03700 30 cephx: service_ticket_blob is 0000 : 01 0a 00 00 00 00 00 00 00 60 00 00 00 aa ed fb : .........`...... 0010 : 31 c2 6a 23 5f 05 13 d8 c5 a5 d7 c2 9e bb 36 b3 : 1.j#_.........6. 0020 : b1 55 5a c3 01 7a bf 4c d7 44 75 4f 13 08 6a b8 : .UZ..z.L.DuO..j. 0030 : fb 78 28 cc c4 51 d7 32 b9 12 99 f2 56 37 f2 f8 : .x(..Q.2....V7.. 0040 : 0f 3c 40 09 39 f8 3a 39 13 e0 b9 7f 6c 86 67 93 : .<@.9.:9....l.g. 0050 : 72 21 e2 25 99 52 a2 7b 76 32 3d 82 cf 5a c1 8f : r!.%.R.{v2=..Z.. 0060 : 65 aa db d8 c2 82 76 20 83 0b b6 a6 37 : e.....v ....7
2017-06-07 02:13:01.625968 7fcebcf03700 10 cephx keyserverdata: get_caps: name=client.admin 2017-06-07 02:13:01.625970 7fcebcf03700 10 cephx keyserverdata: get_secret: num of caps=3 2017-06-07 02:13:01.629389 7fcebcf03700 10 cephx server client.admin: handle_request get_principal_session_key 2017-06-07 02:13:01.629392 7fcebcf03700 10 cephx: verify_authorizer decrypted service auth secret_id=10 2017-06-07 02:13:01.629435 7fcebcf03700 10 cephx: verify_authorizer global_id=59021 2017-06-07 02:13:01.629490 7fcebcf03700 10 cephx: verify_authorizer ok nonce 6b8b4567327b23c6 reply_bl.length()=36 2017-06-07 02:13:01.629493 7fcebcf03700 10 cephx server client.admin: ticket_req.keys = 5 2017-06-07 02:13:01.629495 7fcebcf03700 10 cephx server client.admin: adding key for service mon 2017-06-07 02:13:01.629498 7fcebcf03700 30 cephx keyserverdata: get_service_secret service mon id 117 AQBbTTdZKaCOJBAAQawa1qk9/bRbuxA+CgT37A== expires 2017-06-07 02:48:27.613288 2017-06-07 02:13:01.629529 7fcebcf03700 10 cephx server client.admin: adding key for service osd 2017-06-07 02:13:01.629532 7fcebcf03700 30 cephx keyserverdata: get_service_secret service osd id 117 AQBbTTdZNg+PJBAAQgoJiMojU35X2JU2YcN6+A== expires 2017-06-07 02:48:27.613344 2017-06-07 02:13:01.629550 7fcebcf03700 10 cephx keyserverdata: get_caps: name=client.admin 2017-06-07 02:13:01.629553 7fcebcf03700 10 cephx keyserverdata: get_secret: num of caps=3 2017-06-07 02:13:01.629557 7fcebcf03700 10 cephx: build_service_ticket_reply encoding 2 tickets with secret AQAtYTdZfVFNJRAAbeqZQmRjR0vc889iri1VEA== 2017-06-07 02:13:01.629586 7fcebcf03700 10 cephx: build_service_ticket service mon secret_id 117 ticket_info.ticket.name=client.admin 2017-06-07 02:13:01.629608 7fcebcf03700 30 cephx: service_ticket_blob is 0000 : 01 75 00 00 00 00 00 00 00 60 00 00 00 f0 03 c9 : .u.......`...... 0010 : e4 d4 93 c3 9d cb 14 bf 22 87 36 ea 66 f6 d4 7a : ........".6.f..z 0020 : 97 b6 06 28 8a 9e 7a 14 02 28 b7 e9 18 0d 8c 4e : ...(..z..(.....N 0030 : 13 6a ff 42 90 1b fa 94 2b 45 a2 b4 88 cd 0a 22 : .j.B....+E....." 0040 : 2a db bd 57 4f 19 89 d7 7c 97 88 f4 2d a3 80 69 : *..WO...|...-..i 0050 : b4 12 03 12 63 e6 39 c7 aa 28 e9 af ce 64 7b d9 : ....c.9..(...d{. 0060 : 1f 87 63 e9 3c 11 d8 85 d8 13 33 6b 81 : ..c.<.....3k.
2017-06-07 02:13:01.629705 7fcebcf03700 10 cephx: build_service_ticket service osd secret_id 117 ticket_info.ticket.name=client.admin 2017-06-07 02:13:01.629733 7fcebcf03700 30 cephx: service_ticket_blob is 0000 : 01 75 00 00 00 00 00 00 00 70 00 00 00 a9 5a f8 : .u.......p....Z. 0010 : c5 6b c2 d1 f0 03 fc 6e f6 c2 35 69 b2 8b 18 a4 : .k.....n..5i.... 0020 : 17 5a dc 51 0d 22 d7 f5 bd 13 0f 72 b4 85 d3 1c : .Z.Q.".....r.... 0030 : 60 e4 45 0b 4a 46 fe f3 56 5a 3a 4c db d1 98 15 : `.E.JF..VZ:L.... 0040 : 87 7e 44 02 87 8b da 8c 0d e6 ca 6c 62 e2 28 b1 : .~D........lb.(. 0050 : 4a 56 11 01 bb 7d 41 6a ad 48 71 d7 b2 14 1f 3d : JV...}Aj.Hq....= 0060 : 70 bd 89 ad d0 34 e7 a4 d5 07 30 61 f9 d7 f6 5e : p....4....0a...^ 0070 : 38 47 7e c0 6c 55 96 cc 3a 56 04 1d 3e : 8G~.lU..:V..>
2017-06-07 02:13:02.890379 7fcebd704700 10 cephx keyserver: _check_rotating_secrets |
认证一次的客户端LOG:
2017-06-07 02:13:01.621865 7fcaa56e77c0 5 adding auth protocol: cephx 2017-06-07 02:13:01.622152 7fcaa56e77c0 2 auth: KeyRing::load: loaded key file /etc/ceph/ceph.client.admin.keyring 2017-06-07 02:13:01.625041 7fca9e5de700 10 cephx: set_have_need_key no handler for service mon 2017-06-07 02:13:01.625046 7fca9e5de700 10 cephx: set_have_need_key no handler for service osd 2017-06-07 02:13:01.625048 7fca9e5de700 10 cephx: set_have_need_key no handler for service auth 2017-06-07 02:13:01.625050 7fca9e5de700 10 cephx: validate_tickets want 37 have 0 need 37 2017-06-07 02:13:01.625063 7fca9e5de700 10 cephx client: handle_response ret = 0 2017-06-07 02:13:01.625067 7fca9e5de700 10 cephx client: got initial server challenge 8411847458138444751 2017-06-07 02:13:01.625073 7fca9e5de700 10 cephx client: validate_tickets: want=37 need=37 have=0 2017-06-07 02:13:01.625077 7fca9e5de700 10 cephx: set_have_need_key no handler for service mon 2017-06-07 02:13:01.625079 7fca9e5de700 10 cephx: set_have_need_key no handler for service osd 2017-06-07 02:13:01.625081 7fca9e5de700 10 cephx: set_have_need_key no handler for service auth 2017-06-07 02:13:01.625082 7fca9e5de700 10 cephx: validate_tickets want 37 have 0 need 37 2017-06-07 02:13:01.625085 7fca9e5de700 10 cephx client: want=37 need=37 have=0 2017-06-07 02:13:01.625090 7fca9e5de700 10 cephx client: build_request 2017-06-07 02:13:01.625318 7fca9e5de700 10 cephx client: get auth session key: client_challenge 17269135696729659005 error reading input file openrc: (2) No such file or directory 2017-06-07 02:13:01.626499 7fca9e5de700 10 cephx client: handle_response ret = 0 2017-06-07 02:13:01.626504 7fca9e5de700 10 cephx client: get_auth_session_key 2017-06-07 02:13:01.626512 7fca9e5de700 10 cephx: verify_service_ticket_reply got 1 keys 2017-06-07 02:13:01.626515 7fca9e5de700 10 cephx: got key for service_id auth 2017-06-07 02:13:01.626587 7fca9e5de700 10 cephx: ticket.secret_id=10 2017-06-07 02:13:01.626593 7fca9e5de700 10 cephx: verify_service_ticket_reply service auth secret_id 10 session_key AQAtYTdZfVFNJRAAbeqZQmRjR0vc889iri1VEA== validity=43200.000000 2017-06-07 02:13:01.626615 7fca9e5de700 10 cephx: ticket expires=2017-06-07 14:13:01.626615 renew_after=2017-06-07 11:13:01.626615 2017-06-07 02:13:01.626630 7fca9e5de700 10 cephx client: want=37 need=37 have=0 2017-06-07 02:13:01.626634 7fca9e5de700 10 cephx: set_have_need_key no handler for service mon 2017-06-07 02:13:01.626637 7fca9e5de700 10 cephx: set_have_need_key no handler for service osd 2017-06-07 02:13:01.626639 7fca9e5de700 10 cephx: validate_tickets want 37 have 32 need 5 2017-06-07 02:13:01.626644 7fca9e5de700 10 cephx client: validate_tickets: want=37 need=5 have=32 2017-06-07 02:13:01.626647 7fca9e5de700 10 cephx: set_have_need_key no handler for service mon 2017-06-07 02:13:01.626649 7fca9e5de700 10 cephx: set_have_need_key no handler for service osd 2017-06-07 02:13:01.626651 7fca9e5de700 10 cephx: validate_tickets want 37 have 32 need 5 2017-06-07 02:13:01.626653 7fca9e5de700 10 cephx client: want=37 need=5 have=32 2017-06-07 02:13:01.626656 7fca9e5de700 10 cephx client: build_request 2017-06-07 02:13:01.626658 7fca9e5de700 10 cephx client: get service keys: want=37 need=5 have=32 2017-06-07 02:13:01.631371 7fca9e5de700 10 cephx client: handle_response ret = 0 2017-06-07 02:13:01.631375 7fca9e5de700 10 cephx client: get_principal_session_key session_key AQAtYTdZfVFNJRAAbeqZQmRjR0vc889iri1VEA== 2017-06-07 02:13:01.631394 7fca9e5de700 10 cephx: verify_service_ticket_reply got 2 keys 2017-06-07 02:13:01.631397 7fca9e5de700 10 cephx: got key for service_id mon 2017-06-07 02:13:01.631448 7fca9e5de700 10 cephx: ticket.secret_id=117 2017-06-07 02:13:01.631453 7fca9e5de700 10 cephx: verify_service_ticket_reply service mon secret_id 117 session_key AQAtYTdZetWFJRAAwQx9u2IWLyo4vd57FK3W1g== validity=3600.000000 2017-06-07 02:13:01.631470 7fca9e5de700 10 cephx: ticket expires=2017-06-07 03:13:01.631469 renew_after=2017-06-07 02:58:01.631469 2017-06-07 02:13:01.631480 7fca9e5de700 10 cephx: got key for service_id osd 2017-06-07 02:13:01.631518 7fca9e5de700 10 cephx: ticket.secret_id=117 2017-06-07 02:13:01.631522 7fca9e5de700 10 cephx: verify_service_ticket_reply service osd secret_id 117 session_key AQAtYTdZPS2GJRAAXf3AxV8eApYSf5FwQC/ArQ== validity=3600.000000 2017-06-07 02:13:01.631536 7fca9e5de700 10 cephx: ticket expires=2017-06-07 03:13:01.631536 renew_after=2017-06-07 02:58:01.631536 2017-06-07 02:13:01.631545 7fca9e5de700 10 cephx: validate_tickets want 37 have 37 need 0 2017-06-07 02:13:01.631604 7fca9e5de700 10 cephx: validate_tickets want 37 have 37 need 0 2017-06-07 02:13:01.631609 7fca9e5de700 20 cephx client: need_tickets: want=37 need=0 have=37 |
官方原文:
Ceph X protocol
First, the principal has to authenticate withthe authenticator. A
shared-secret mechanism is being used, andthe negotitaion goes like this:
A = Authenticator
P = Principle
S = Service
1. Obtaining principal/auth session key
(Authenticate Request)
p->a : principal, principal_addr. authenticate me!
...authenticator does lookup in database...
a->p : A= {principal/auth session key,validity}^principal_secret (*)
B= {principal ticket, validity,principal/auth session key}^authsecret
[principal/auth session key, validity] =service ticket
[principal ticket, validity, principal/authsession key] = service ticket info
(*) annotation: ^ signifies 'encrypted by'
At this point, if is genuine, the principalshould have the principal/auth
session key at hand. The next step would beto request an authorization to
use some other service:
2. Obtaining principal/service session key
p->a : B, {principal_addr,timestamp}^principal/auth session key. authorize
me!
a->p : E= {service ticket}^svcsecret
F= {principal/service session key,validity}^principal/auth session key
principal_addr, timestamp = authenticator
service ticket = principal name, clientnetwork address, validity, principal/service session key
Note that steps 1 and 2 are pretty much thesame thing; contacting the
authenticator and requesting for a key.
Following this the principal should have aprincipal/service session key that
could be used later on for creating asession:
3. Opening a session to a service
p->s : E + {principal_addr,timestamp}^principal/service session key
s->p :{timestamp+1}^principal/service/session key
timestamp+1 = reply authenticator
Now, the principal is fully authenticatedwith the service. So, logically we
have 2 main actions here. The first one wouldbe to obtain a session key to
the service (steps 1 and 2), and the secondone would be to authenticate with
the service, using that ticket.
该内容在源码中的/src/auth/cephx/CephxProtocol.h的注释中