Macaroons Escalated Quickly
Bài tóm tắt Fly.io 2024 3. Quy mô lớn Độ khó: Khó
Fly.io · 2024 · 3. Quy mô lớn · Độ khó: Khó — bài gốc
Bài của Thomas Ptacek (Fly.io), giọng văn rất chủ quan; nhận định ghi "theo Fly.io".
Bối cảnh
- API token của Fly.io (OAuth2) quá nhiều quyền: mỗi token là vé vào toàn bộ tài khoản; cần thu hẹp và biểu diễn vai trò. Dự án mở rộng thành thay hẳn OAuth2 bằng Macaroon (thiết kế của Google, NDSS 2014, ít ai triển khai thật).
- Theo Fly.io, là một public cloud thì khách muốn đủ kiểu phân quyền; mục tiêu là thiết kế hệ phân quyền một lần rồi khỏi phải nghĩ tới nữa.
Thay đổi chính
- Macaroon: token mang chuỗi "caveat", mỗi caveat được ký bằng HMAC với khoá là HMAC của bước trước. Thêm caveat không cần khoá của server, nên user tự thu hẹp token của mình (ví dụ chỉ đọc, chỉ một app, có hạn dùng, chỉ dùng từ một Fly Machine); caveat chỉ có thể làm token yếu đi. Mô hình hoá nền tảng bằng caveat (Organization, App, Machine, Volume × Read/Write/Create/Delete/Control) thay vì định nghĩa vai trò trước: token admin, token user, token chỉ để kiểm toán, token cho CI/CD deploy đều tự tạo được.
- Third-party caveat: caveat trỏ tới một dịch vụ khác (SSO, kiểm toán, thu hồi…); muốn dùng token phải đổi "vé" lấy một discharge macaroon từ dịch vụ đó. Ứng dụng: mọi token đều có caveat trỏ tới dịch vụ đăng nhập, nên token chỉ chứa quyền, không chứa xác thực, gần như gửi email được; bắt buộc SSO Google/GitHub theo từng Organization (prod hai lớp, dev không cần); một bot Slack có thể duyệt request mà nền tảng không biết gì về Slack. Theo Fly.io, đó là một hệ plugin cho token bảo mật.
- Triển khai: tự viết (Go, sau có Elixir; SHA256, ChaCha-Poly, MsgPack) thay vì dùng thư viện mở, vì cộng đồng dùng caveat dạng blob không kiểu. Vì ai kiểm được HMAC thì cũng tạo được token, họ tách "verification" (chỉ chạy trên một dịch vụ xác minh cách ly vật lý, gọi qua HTTP, kết quả cache được, dữ liệu trên SQLite phân tán bằng LiteFS nên nhanh ở mọi nơi; token OAuth2 cũ chỉ nhanh ở Ashburn) khỏi "clearing" caveat (làm ở đâu cũng được).
- Service token: worker cần secret của khách (ví dụ khoá giải mã volume) cả khi app khởi động lại hay chuyển máy, nhưng không được tự quyết lấy secret nào. Dịch vụ xác minh đổi token của user thành service token (bỏ caveat xác thực và hạn dùng); thành phần nhận có thể thu hẹp tiếp, ví dụ khoá vào đúng một Fly Machine, nên lộ token từ máy đó cũng vô dụng ở nơi khác. Cách này cho phép mở API cho VM của khách mà không có lỗi kiểu IMDSv1.
- Thu hồi theo nonce của token gốc (huỷ mọi token suy ra từ nó); cache token trên toàn fleet kiểm tra danh sách thu hồi thường xuyên.
Vì sao
- Token thu hẹp được tại chỗ (least privilege lúc cần) giảm thiệt hại khi lộ; tách xác thực khỏi phân quyền và đẩy chính sách ra dịch vụ bên ngoài qua caveat thay vì gom vào nền tảng.
- Theo Fly.io: mất hơn 2 năm và khá phức tạp; caveat chỉ thu hẹp nên biểu diễn vài vai trò hơi gượng; họ dùng ID nội bộ của DB làm định dạng caveat công khai, một quyết định họ tự nhận là sai.
Bài học cho SWE
- Phân quyền mô hình hoá theo tài nguyên + thao tác, để người dùng tự ghép vai trò, đỡ hơn định nghĩa trước mọi vai trò.
- Thứ kiểm được chữ ký mà cũng tạo được chữ ký (HMAC) phải nằm sau một dịch vụ cách ly.
- Credential cho máy chủ nên suy ra từ hành động của khách và bị khoá vào đúng máy dùng nó.
Liên quan
- Xác thực và phân quyền (authn/authz)
- Fly.io 2023 (orchestrator truyền token) · Slack 2023 (credential lấy từ metadata service)
- Bảo mật hạ tầng và quản lý secret · Nền tảng nội bộ cho service (đường ray chung)
Bảo mật hạ tầng và quản lý secretNền tảng nội bộ cho service (đường ray chung)Xác thực và phân quyền (authn/authz)
#API token#Macaroon#Chained HMAC#Caveat#Attenuation#Third-party caveat#Discharge#SSO#Token verification service#Service token#Revocation#LiteFS#Least privilege
Được nhắc tới trong
Chủ đề (3)
Công ty (1)
Bài tóm tắt (4)