Đề xuất cập nhật tự động (AGT-12), gửi nhóm Collector
Trạng thái: ĐỀ XUẤT, chưa xây. Agent KHÔNG đổi giao thức từ phía mình. Tài liệu này nêu điều agent cần ở GET /agent/v1/update (COL-16) để nhóm Collector xem, sửa hoặc từ chối trước khi viết mã. Nguồn sự thật của giao thức vẫn là docs/03-protocol.md của repo collector (mục 2.7) và ADR 0005 (không thực thi mã từ xa: cập nhật chỉ là thay chính binary agent bằng bản đã ký, không chạy gì khác).
1. Điều đã có trong hợp đồng
UpdateManifest{version, url, sha256, signature_ed25519, min_version, rollout_percent, released_at_ms} và truy vấn os, arch, version, channel, trả 204 khi không có bản mới. Collector chọn cohort bằng hash(agent_id) mod 100 < rollout_percent và có công tắc dừng khẩn cấp.
2. Điều agent cần làm rõ hoặc bổ sung
| # | Đề xuất | Lý do |
|---|---|---|
| P1 | Chữ ký phải phủ cả os, arch, channel, size chứ không chỉ version và sha256 | Chặn phát lại manifest hợp lệ của nền tảng hoặc kênh khác (ví dụ binary Windows cho máy Linux, kênh beta cho máy stable) |
| P2 | Thêm os, arch, channel, size_bytes, key_id vào UpdateManifest | Agent kiểm tra khớp trước khi tải, từ chối tải quá size_bytes (trần cứng 40 MiB), chọn khóa công khai đúng khi xoay khóa |
| P3 | Thêm revoked_versions (danh sách phiên bản bị cấm chạy, nằm trong phần được ký) | Thu hồi bản lỗi hoặc bản có lỗ hổng: máy đang chạy bản bị cấm sẽ nâng cấp ngay cả khi ngoài cohort, và tuyệt đối không được cập nhật xuống bản bị cấm |
| P4 | rollout_percent và công tắc dừng khẩn cấp KHÔNG nằm trong phần được ký, collector tự quyết bằng 204 | Dừng khẩn cấp phải tác dụng tức thì mà không cần ký lại. Thành phần cohort chỉ ảnh hưởng thời điểm, không ảnh hưởng nội dung, nên không cần ký |
| P5 | url phải là https, host nằm trong tập host do collector khai báo, không chuyển hướng sang host khác | Agent không tải từ nơi tùy ý nếu manifest bị sai. Sha256 và chữ ký mới là rào chắn thật, không phải TLS |
| P6 | Mô tả ngữ nghĩa min_version (mục 4) | Hiện chỉ có tên trường |
3. Bytes được ký
Chữ ký Ed25519 trên chuỗi UTF-8 sau, các trường nối bằng ký tự xuống dòng \n, không có khoảng trắng thừa, số viết thập phân không số 0 đầu, sha256 là 64 ký tự hex thường, revoked_versions sắp xếp tăng dần theo chuỗi rồi nối bằng dấu phẩy (rỗng thì để trống):
accesshub-agent-update-v1
<version>
<os>
<arch>
<channel>
<sha256>
<size_bytes>
<min_version>
<released_at_ms>
<revoked_versions>
<url>Tiền tố cố định là tách miền ký: một chữ ký dùng cho mục đích khác (ví dụ ký gói) không thể dùng làm manifest. url nằm trong phần ký để không thể hoán đổi nơi tải. Agent dựng lại đúng chuỗi từ các trường nhận được rồi xác minh, không tin chuỗi do collector gửi sẵn. Phiên bản bố cục đổi thì đổi tiền tố (-v2).
4. Ngữ nghĩa phiên bản
- Phiên bản theo semver
MAJOR.MINOR.PATCH(có thể có hậu tố tiền phát hành, so sánh theo semver). - Agent chỉ cập nhật khi
versionlớn hơn bản đang chạy NGHIÊM NGẶT và không nằm trongrevoked_versions. Không bao giờ hạ cấp theo manifest, kể cả khi manifest hợp lệ (chặn tấn công phát lại bản cũ có lỗ hổng). Hạ cấp là thao tác thủ công của quản trị viên. min_versionlà bản thấp nhất được phép áp dụng bản cập nhật này trực tiếp. Bản đang chạy thấp hơnmin_versionthì agent không áp dụng, ghi cảnh báo trongstatus, và collector phải phục vụ bản trung gian (nâng cấp theo bậc cho các thay đổi định dạng dữ liệu).- Quay lui: sau khi thay binary, bản mới phải gửi thành công một lô số liệu (
MetricsAck) trong 5 phút, nếu không agent tự trả về binary cũ (còn lưu) và đánh dấu phiên bản đó "đã thất bại" để không thử lại trong 24 giờ. Quay lui chỉ là hành vi cục bộ, không cần giao thức.
5. Luồng phía agent (khi xây)
- Kiểm tra định kỳ 6 giờ cộng lệch ngẫu nhiên theo
agent_id(không phải mọi máy cùng lúc), chỉ khiupdate.enabled(mặc định tắt cho bản cài bằng gói, xem mục 6). GET /updatevớios,arch(lấy từruntime, không nhận từ cấu hình),version,channel.- Dựng bytes ký, xác minh bằng khóa công khai nhúng trong binary (hai khóa, chọn theo
key_id, hỗ trợ xoay khóa). Sai chữ ký, saios/arch/channel,size_bytesquá trần,urlsai quy tắc P5: bỏ manifest, ghi một cảnh báo, KHÔNG tải gì. - Tải vào thư mục tạm của agent, băm sha256 khi tải, dừng nếu vượt
size_bytes, so sánh vớisha256đã ký. Chưa khớp thì xóa. - Chỉ sau khi khớp mới chuyển sang bước áp dụng (mục 6). Agent không thực thi tệp tải về ngoài việc thay thế đã mô tả, và tệp tải về không bao giờ được chạy trước khi xác minh xong.
6. Vấn đề quyền hạn: cần quyết định của chủ dự án
Dịch vụ chạy bằng tài khoản không đặc quyền (accesshub-agent trên Linux, ADR 0008 trên Windows) và unit systemd có ProtectSystem=strict, nên agent KHÔNG ghi đè được /usr/bin/accesshub-agent hay C:\Program Files\AccessHubAgent. Có ba hướng:
| Phương án | Mô tả | Đánh đổi |
|---|---|---|
| A | Bản cài bằng gói (deb, rpm, MSI) chỉ cập nhật bằng trình quản lý gói (apt, dnf, GPO, Intune). Bộ cập nhật tự động tắt | Không thêm mã đặc quyền. Cập nhật chậm hơn, không có đợt triển khai và dừng khẩn cấp từ trung tâm |
| B | Agent xác minh và đặt bản mới vào thư mục staging, một đơn vị đặc quyền nhỏ riêng (systemd .path + oneshot chạy root, hoặc dịch vụ SYSTEM trên Windows) xác minh LẠI chữ ký độc lập rồi thay binary và khởi động lại | Có đợt triển khai và dừng khẩn cấp. Thêm một thành phần chạy quyền cao, phải giữ cực nhỏ, kiểm thử riêng, và vẫn không thực thi gì từ manifest |
| C | Nới ProtectSystem, cho tài khoản dịch vụ ghi vào thư mục binary | Không khuyến nghị: tài khoản dịch vụ bị chiếm là thay được binary chạy trên mọi máy |
Khuyến nghị: A cho mọi bản cài bằng gói ngay từ đầu, B làm sau cho khách hàng cần đợt triển khai tập trung, không bao giờ C. Chọn phương án nào cũng cần khóa ký Ed25519 và khóa GPG, Authenticode (Q3) trước khi viết mã.
7. Cô lập khách hàng
Binary agent là cùng một tệp cho mọi công ty, nên manifest không chứa dữ liệu công ty. Yêu cầu GET /update mang token agent, collector lấy agent_id từ token để chọn cohort, KHÔNG nhận company_id hay agent_id từ truy vấn. Agent không gửi gì ngoài os, arch, version, channel. Một công ty không thể đưa bản cập nhật riêng cho máy của công ty khác, vì chỉ phát hành từ khóa ký gốc.
8. Thử nghiệm bắt buộc khi xây
Manifest sai chữ ký, đổi từng trường đã ký (mỗi trường một ca), os/arch/channel không khớp, quá size_bytes, sha256 sai, url http hoặc host lạ, chuyển hướng sang host khác, hạ cấp, bản bị thu hồi, min_version cao hơn bản đang chạy, mất điện giữa chừng khi thay binary (binary cũ còn nguyên), bản mới không gửi được lô nào (quay lui), khóa xoay (hai khóa), phiên bản đã đánh dấu thất bại không thử lại trong 24 giờ.
9. Câu hỏi cho nhóm Collector
- Chấp nhận P1 đến P6 hay đề xuất cách khác cho cùng mục tiêu?
- Collector lưu và phục vụ binary, hay
urltrỏ tới kho khác (GitHub Releases, bucket)? Ảnh hưởng quy tắc P5. - Kênh nào có (
stable,beta) và agent chọn kênh bằng cấu hình cục bộ hay cấu hình từ xa? Đề xuất: chỉ cục bộ, để cấu hình từ xa không đẩy máy sang kênh thử nghiệm.