Tìm hiểu Token trong Keystone.
1.Khái niệm.
- Token được sử dụng để xác thực và ủy quyền cho giao tiếp với các Openstack API khác nhau. Token có nhiều phạm vi, đại diện cho nhiều mức độ và nguồn ủy quyền khác nhau.
- Token cũng được sử dụng để chuyển tiếp phân công vai trò của người dùng. Một người dùng có thể có nhiều vai trò, quyền trên các project và domain. Đó được gọi là phạm vi ủy quyền, mà một token hoạt động trong một scope duy nhất.
- Mỗi phạm vi ủy quyền hữu ích cho các loại hoạt động nhất định trên các service nhất định của Openstack và không thể thay thế.
- Unscoped tokens: Không chứa catalog, role, project hay domain scope. Nó được sử dụng trong trường hợp để cung cấp định danh cho người dùng( để tạo ra scoped token), mà không cần lặp lại thông tin đăng nhập ban đầu.
- Project token: đại diện cho ủy quyền của người dùng trong một hợp đồng thuê cloud và hữu ích để xác thực khi làm việc với tất cả các service khác. Nó chứa thông tin về service catalog, bộ các role, mà chi tiết vê project mà người dùng có ủy quyền.
- Domain-scoped token: nó thể hiện sử ủy quyền đối với một cấp độ domain, hữu ích khi làm việc với một domain duy nhất. Nó chứa một số lượng giới hạn service catalog, role, và chi tiết về project mà có ủy quyền.
- System-scoped token: được sử dụng khi yêu cầu các API làm việc với hệ thống triển khai, đại diện cho vai trò của một user đối với hệ thống triển khai.
2. Token provider.
Loại token được cung cấp bởi keystone có thể cấu hình thông qua file /etc/keystone/keystone.conf . Hiện tại (Train và Stein) có hai token provider được hỗ trợ là Fernet và JWS. Ngoài ra một số phiên bản cũ hỗ trợ các keystone provider như UUID, PKI.
2.1.Token provider.
- Kích thước nhỏ gọn, là chuỗi ký tự ngẫu nhiên gồm 32 ký tự.
- Tạo nên từ các chỉ số hệ thập lục phân
- Token URL thân thiện và an toàn khi gửi qua môi trường non-binary.
- Bắt buộc phải lưu trữ tại một backend(như SQL database) để sẵn sàng cho mục đích xác thực.
- UUID token không bị xóa khỏi hệ thống nhưng sẽ được đánh dấu là “revoked” (đã bị thu hồi) thông qua DELETE request với token tương ứng.
- Token là rất nhỏ và dễ sử dụng khi accessing Keystone thông qua cURL command.
-
Nhược điểm của dạng token này là Keystone phải giao tiếp với backend để xác thực, với yêu cầu xác thực lớn có thể làm giảm hiệu năng của keystone.
- Quá trình tạo UUID token:
- User gửi yêu cầu đến keystone tạo token với các thông tin: username, password, project name.
- Keystone xác thực user, và lấy userid từ backend LADP hay SQL.(dịch vụ Identify)
- Chứng thực project, thu thập thông tin Project ID và Domain ID từ Backend SQL.(dịch vụ resource)
- 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 service và các endpoint 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
- Quá trình kiểm tra và thu hồi token:
- User gửi yêu cầu chứng thực token sử dụng method GET v3/auth/tokens
- Thu thập token payload từ token backend KVS/SQL.
- Kiểm tra Vaild field value. Nếu không hợp lệ trả về thông báo “Token Not Found”. Nếu hợp lệ, chuyển sang bước tiếp theo:
- Phân tích Token và thu thập metadata (User ID, Project ID, Audit ID, Token Expiry)
- Check Current Time, nếu Current Time > Expiry Time thì gửi thông báo “Token Not Found”, ngược lại chuyển sang bước tiếp theo.
- Kiểm tra xem token đã bị thu hồi chưa (kiểm tra trong bảng revocation_event của database keystone). Nếu token đã bị thu hồi (tương ứng với 1 event trong bảng revocation_event) trả về thông báo Token Not Found. Nếu chưa bị thu hồi trả về token (truy vấn HTTP thành công HTTP/1.1 200 OK )
2.2. PKI/PKIZ token
- 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.
2.3. Fernet.
-
Được giới thiệu từ bản Openstack Kilo và hiện tại là token provider mặc định. Fernet token không cần phải lưu ở trong backend. Mã hóa AES256 được sử dụng để bảo vệ thông tin lưu trữ trong token và tính toàn vẹn được xác minh bằng chữ ký SHA256 HMAC. Chỉ Identity service mới có quyền truy cập vào các khoá được sử dụng để mã hoá và giải mã fernet token. Giống như UUID token, fernet token phải được gửi lại cho Identity service để xác thực chúng.
-
Việc triển khai có thể xem xét sử dụng fernet provider trái ngược với JWS provider nếu họ lo ngại về việc công khai payload sử dụng để build tokens.
2.4. JWS token
- Định dạng JSON Web Signature (JSW) token là một loại JSON Web Token và nó đã được triển khai từ bản Openstack Stein. JWS đã được sign, nó có nghĩa là thông tin được sử dùng để tạo token có thể được nhìn thấy bởi người dùng và bất cứ ai cũng có thể giải mã nó. JWS token là tạm thời, nghĩa là không cần phải lưu trữ trong database hay là phải nhân bản trên nhiều node. Vì JWS token provider sử dụng khoá không đối xứng, token được ký bằng private key và xác thực bằng public key. JWS token provider chỉ hỗ trợ ES256 JSON Web Algorithm (JWA), là thuật toán ECDSA sử dụng đường cong P-256 và SHA-256
3. Fernet.
3.1. Fernet token là gì?
- Là token đại diện cho xác thực của người dùng. Fernet token chứa một lượng giới hạn các dữ liệu xác thực và ủy quyền trong một đoạn mã MessagePacked. Sau đó đoạn mã được gói như một tin nhắn Fernet để chuyển đi, nơi Fernet cung caaos những đặc điểm an toàn web cần thiết cho URL và header. Dữ liệu bên trong Fernet token được bảo vệ bởi cặp key mã hóa đối xứng, hoặc là fernet key.
3.2. Fernet key là gì?
- Fernet key được được sử dụng để mã hóa và giải mã fernet token. Mỗi key bao gồm 2 key nhỏ hơn: 128 bit key mã hóa AES, 128 bit key chữ ký SHA256 HMAC. Các key được lưu trữ trong key repository mà keystone sẽ chuyển nó đến thư viện để xử lý việc mã hóa và giải mã token.
3.3. Các loại key khác nhau
- Key repository được yêu cầu bởi keystone để có thể tạo fernet token. Những key này được sử dụng để mã hóa và giải mã thông tin trong token. Mỗi key trong repository có thể có một tron ba trạng thái. Trạng thái của Key cho biết keystone đang sử dụng key như thế nào. Có 3 trạng thái là:
- Primary key: Chỉ có duy nhất một primary key trong một key repository, nó được phép mã hóa và giải mã tokens. Key này luôn được đặt tên theo chỉ số cao nhất trong repository.
- Secondary key: Ở một thời điểm là primary key, nhưng bị hạ cấp để sử dụng một primary key khác. Secondary key chỉ được phép giải mã token. Vì nó từng là primary key tại một thời điểm nào đó nên Keystone vẫn cần nó để có thể giải mã các token mà được tạo bởi key này trước đây.
- Staged key: Là một loại key đặc biệt có một số đặc điểm như secondary key. Bắt buộc phải có ít nhất và duy nhất một key trong một repository. Giống secondary key, Staged key chỉ có khả năng giải mã token. Nhưng nó chưa từng là primary key mà nó được sẽ là primary key kế tiếp. Key này luôn có tên là 0.
- Cấu hình key repository được lưu ở đâu bằng tùy chọn key_repository trong file cấu hình của keystone. Hiện tại keystone chỉ hỗ trợ lưu key repo dưới dạng tập tin:
[fernet_tokens] key_repository = /etc/keystone/fernet-keys/
3.4. Rotate Fernet key.
- Hình dưới đây mô tả quá trình rotate fernet key
- Bước đầu chưa có key repo sẽ khởi tạo một key repo bằng `keystone-manager` để tạo hai key trong repo. Khi hai file được tạo thì sẽ có file tên 1 là primary key và file 0 sẽ là staged key và không có secondary key.
- Lần rotate đầu tiên, staged 0 sẽ trở thành primary key 2, primary key 1 trở thành secondary key và staged mới sẽ được tạo ra với file name là 0.
- Lần rotate thứ 2, staged 0 trở thành primary key 3, primary key 2 trở thành secondary key 2, secondary 1 giữ nguyên và tạo ra staged key mới.
- Sử dụng fernet token đòi hỏi nhận thức về một việc hết hạn token và key lifecycle. Nếu rotate nhiều đến mức xóa đi secondary key trong khi nó vẫn cần để có thể giải mã các token mà nó tạo ra chưa hết hạn, keystone sẽ không thể giải mã token này. Chỉ xóa key khi mà bạn biết chắc chắn rằng nó không còn được sử dụng để mã hóa hay giải mã token nữa.
Ví dụ, token có hạn là 24h và muốn rotate key mỗi 6h. Chúng ta sẽ phải cấu hình để token tạo lúc 8h sáng thứ 2 vẫn sử dụng được vào 7h50 sáng thứ 3, giả sử như token không bị thu hồi sớm. Để làm được điều này thì chúng ta sẽ cấu hình max_active_keys=6 trong file cấu hình keystone. Tùy chọn này sẽ cho phép keystone giữ tối đa 6 key một lúc, do đó, nó sẽ giữ được 1 primary key, 1 staged key và 4 secondary key. Có thể được minh họa như sau:
token_expiration = 24
rotation_frequency = 6
max_active_keys = (token_expiration / rotation_frequency) + 2
3.5. Các trường của Fernet token.
- Fernet Format Version (0x80): 8 bits, biểu thị phiên bản của định dạng token.
-
Current Timestamp: Số nguyên 64-bits không dấu, chỉ nhãn thời gian tính theo giây, tính từ 01/01/1970, chỉ ra thời điểm token được tạo ra.
-
Initialization Vector (IV): Key 128-bits sử dụng mã hoá AES và giải mã Ciphertext.
-
Ciphertext: Là keystone payload kích thước biến đổi tuỳ vào phạm vi của token. Cụ thể hơn, với token có phạm vi project, Keystone payload bao gồm: version, user id, method, project id, expiration time, audit id.
- HMAC: 256-bits SHA256 HMAC (Keyed-Hash Message Authentication Code) - Mã xác thực thông báo sử dụng hàm một chiều có khoá với signing key kết nối 4 trường ở trên.
3.6. Quá trình tạo fernet token.
3.7.
Nguồn: https://docs.openstack.org/keystone/stein/admin/tokens.html https://github.com/doedoe12/Internship/blob/master/Openstack/02.Keystone/02.Token.md