- Token được sử dụng trong Keystone để xác thực và ủy quyền cho phép các tương tác của người dùng tới các API endpoint. Token có nhiều loại đại diện cho nhiều kiểu xác thực và nhận dạng . Có rất nhiều
token provider
mỗi provider có đặc tính rieeng cho quá trình phát triển - Token có thể dùng để thực hiện ủy quyền trên nhiều phạm vi khác nhau . Người dùng sẽ có mỗi đặc quyền riêng bởi các role, trên các project và domain . Mỗi phạm vi sẽ ảnh hưởng đến các service nằm trong phạm vi đó .
- Unscoped token không tác động đến service , catalog, project, domain . Khi sử dụng unscoped token thì chỉ mang tính đạng danh, không được tương tác với các compoment khác
- Project-scoped token : được sử dụng để có thể tác động tới các serivce khác. Chúng chưa các catalog , role và các thông tin của project và được ủy quyền
- Domain-scoped token : được sủ dụng ít, có thể làm việc tới các đối tưowngj dưới domain,
Token provider trong keystone được cấu hình tại /etc/keystone/keystone.conf
. Hiện tại có 4 kiểu token provider hỗ trợ : UUID
fernet
, PKI
và PKIZ
-
Kích thước nhỏ gọn, là chuỗi ngẫu nhiên 32 ký tự
-
Tạo nên từ các chỉ số hệ thập lục phân
-
Tokens URL thân thiện và an toàn khi gửi đi trong môi trường non-binary.
-
Lưu trữ trong hệ thống backend (như database) bề vững để sẵn sàng cho mục đích xác thực
-
UUID không bị xóa trong hệ thống lưu trữ nhưng sẽ bị đánh dấu là "revoked" (bị thu hồi) thông qua DELETE request với token ID tương ứng.
-
UUID không mang thông tin gì về User. Keystone phải thực hiện việc xác thực token và lưu trữ, với kích thước của hệ thống mở rộng hơn thì hiệu xuất của Keystone sẽ bị ảnh hưởng.
-
Workflow tạo UUID token diễn ra như sau:
- User request tới keystone tạo token với các thông tin: user name, password, project name
- Chứng thực user, lấy User ID từ backend LDAP (dịch vụ Identity)
- Chứng thực project, thu thập thông tin Project ID và Domain ID từ Backend SQL (dịch vụ Resources)
- Lấy ra Roles từ Backend trên Project hoặc Domain tương ứng trả về cho user, nếu user không có bất kỳ roles nào thì trả về Failure(dịch vụ Assignment)
- Thu thập các Services và các Endpoints của các service đó (dịch vụ Catalog)
- Tổng hợp các thông tin về Identity, Resources, Assignment, Catalog ở trên đưa vào Token payload, tạo ra token sử dụng hàm uuid.uuid4().hex
- Lưu thông tin của Token và SQL/KVS backend với các thông tin: TokenID, Expiration, Valid, UserID, Extra
PKI token chứa toàn bộ thông tin xác thực nhận được từ Keystone. Điều này có nghĩa là token chứa lượng lớn các thông tin: như là thời gian cấp phát, thời gian hết hạn, định danh user, thông tin project, domain và role cho user, catalog dịch vụ, và nhiều thông tin khác. Chính vì mang quá nhiều thông tin nên nó lại là điểm yếu của loại token này vì khi hệ thống được mở rộng các thông tin user và catalog càng nhiều trong khi đó HTTP Header chỉ giới hạn 8KB.
Để khác phục điều này thì Openstack cũng đưa ra một loại token PKIZ với khả năng nén token xuống kích thước tối thiểu. Mặc dù đã được nén nhưng PKIZ vẫn bị cộng đồng Openstack đánh giá là kích thước quá lớn. Ưu điểm của loại token này là các OpenStack services có thể cache lại token này để đưa ra quyết định ủy quyền mà không phải liên hệ lại keystone nên đã giải quyết được vấn đề tắc nghẽn cổ chai của UUID token.
Cũng giống như UUID token với PKI và PKIZ token thì User cần gửi các thông tin để Keystone xác thực và cấp token, nhưng có một điểm khác là loại token này sử dụng hệ mật mã khóa bất đối xứng tức là dùng khóa Private Key của keystone để mã hóa Payload token, khi user sử dụng token này thì các service trong Openstack sẽ sử dụng Public Key để giải mã và lấy ra các thông tin. Các bước khởi tạo token PKI được thể hiện rất rõ ở hình ảnh trên.
Quá trình này hoàn toàn tương tự vơi UUID token. Quá trình thu hồi cũng hoàn toàn tương tự UUID token.
- Fernet token được sử dụng đầu tiền tại Openstack Kilo . Không giống như các loại token khác fernet không yêu cầu sử dụng backend
- Fernet token chưa một số lượng dữ liệu nhận dạng và ủy quyền trong MessagePacked . Payload sẽ đóng gói các Fernet token . Dữ liệu trong Fernet token được bảo vệ bởi các thuật toán mã hóa đối xứng hoặc 2 fernet key
- Fernet key được dùng trong việc mã hóa và giải mã các Fernet token. Trong mỗi kernet key bao gồm 2 khóa hỏ hơn : a 128-bit AES256 encryption key và . 128-bit SHA256 HMAC signing key . Fernet key được lưu tại key respo mà payload có thể chuyển đến thư viện xử lý mã hóa và giải mã mã token
- Fernet sẽ đến thư mục chứa các key, thực hiện tất cả mã hóa bằng cách sử dụng khóa đầu tiên trong danh sách và cố gắng giải mã bằng tất cả các khóa từ danh sách đó. Keystone fernet token trông giống như sau:
gAAAAABWHXT73mGHg90PE6rmS-6aeYYvdErvO1RCWbDBrM5JV6L-eGEkz9cv8598DWWF5LZH5buzYM6PmUk3w9PHd4j6zs9L0_nvqZAGOrA4gLjhE10MLk00_Qy-IIPMQ6kxjsphYVLP1uBUNyh-s4hq76-KGNUqAcYgLyN8DtgoifDseSZKNl8
-
Key repo là yêu cầu tối thiểu để khởi tạo một fernet token. Những key được lưu trong repo nhăm mục đích mã hóa và giải mã trong quá trình đóng gói fernet token .Mỗi key trong repo có thể có một trong ba trạng thái. Trạng thái của khóa xác định cách keystone sử dụng fernet token. Các loại khác nhau như sau:
-
Loại 1 - Primary Key: sử dụng cho cả 2 mục đích mã hóa và giải mã fernet tokens. Các key được đặt tên theo số nguyên bắt đầu từ 0. Trong đó Primary Key có chỉ số cao nhất.
-
Loại 2 - Secondary Key: chỉ dùng để giải mã. -> Lowest Index < Secondary Key Index < Highest Index
-
Loại 3 - Stagged Key: tương tự như secondary key trong trường hợp nó sử dụng để giải mã token. Tuy nhiên nó sẽ trở thành Primary Key trong lần luân chuyển khóa tiếp theo. Stagged Key có chỉ số 0 -- Fernet Keys được lưu tại
/etc/keystone/fernet-keys/
-
- Bước đầu chưa có key repo sẽ khởi tạo một key repo bằng
keystone-manager
để tạo 2 khóa trong repo. Khi 2 file được tạo thì sẽ có file tên 1 sẽ là primary key , và file 0 sẽ là staged key và không có một secondary key - Xem đây là lần đầu xoay vòng , hiện tại đã có 2 file 0, 1 nên index tiếp theo sẽ là 2 . Fernet repo thực hiện , staged key ( 0 ) sẽ trở thành primary key với tên file 2 . và primary key (1 ) sẽ trờ thành secondary file. và thêm mới một strage với tên file là 0
- Trong lần xoay tiếp theo, index lớn nhất sẽ là 3 , staged key ( 0 ) sẽ trở thành primary key với file 3 , primary key ( 2 ) sẽ trở thành secondary ( 2 )
- Gửi yêu cầu xác thực token với phương thức: GET v3/auth/tokens
- Khôi phục lại padding, trả lại token với padding chính xác
- Decrypt sử dụng Fernet Keys để thu lại token payload
- Xác định phiên bản của token payload. (Unscoped token: 1, token trong tầm vực domain: 1, token trong tầm vực project: 2 )
- Tách các trường của payload để chứng thực. Ví dụ với token trong tầm vực project gồm các trường sau: user id, project id, method, expiry, audit id
- Kiểm tra xem token đã hết hạn chưa. Nếu thời điểm hiện tại lớn hơn so với thời điểm hết hạn thì trả về thông báo "Token not found". Nếu token chưa hết hạn thì chuyển sang bước tiếp theo
- Kiểm tra xem token đã bị thu hồi chưa. Nếu token đã bị thu hồi (tương ứng với 1 sự kiện thu hồi trong bảng revocation_event của database keystone) thì trả về thông báo "Token not found". Nếu chưa bị thu hồi thì trả lại token (thông điệp phản hồi thành công HTTP/1.1 200 OK )
[1] : https://developer.ibm.com/opentech/2015/11/11/deep-dive-keystone-fernet-tokens/