ADR 0001Chấp nhận
ADR 0001. Tách đặc quyền trong gói Access Hub Scanner: bộ đọc không mạng, bộ gửi riêng không đặc quyền
- Trạng thái: Chấp nhận (2026-10-02). Chủ dự án duyệt Q1 (phương án b2), Q6 (tài khoản riêng với
CAP_DAC_READ_SEARCH) và quyết định Q25: Access Hub Scanner là sản phẩm, gói cước riêng, không phụ thuộc Access Hub Agent theo bất kỳ chiều nào. Bản đề xuất trước (Agent chuyển tiếp spool) bị thay bằng bộ gửi riêng của gói Scanner. - Bằng chứng: spike S4 (
docs/spikes/README.md): unit của bộ đọc đạt 1,1 ởsystemd-analyze security; chạy thật trong hộp cát seccomp,AF_UNIX,MemoryMax: quét được, không tạo được socket mạng. Còn phải thử trên máy có root: ambient capability thật,IPAddressDeny(BPF), systemd cũ (CentOS 7). - Ngày: 2026-10-02
Bối cảnh
Quét bảo mật cần đọc tệp chỉ root đọc được (/etc/shadow, /etc/sudoers, thư mục bị giới hạn khi duyệt tệp). Sản phẩm có các ràng buộc đã chấp nhận: chỉ đi ra (ADR 0001 của Access Hub Collector), không thực thi từ xa (ADR 0005 của Agent, ADR 0010 của Collector), tiến trình chạy không đặc quyền khi có thể. Chủ dự án quyết định (Q25): quét bảo mật là sản phẩm và gói cước riêng; các công cụ là gói riêng, không bao giờ phụ thuộc nhau. Khách hàng chỉ mua Scanner không cần cài Agent; khách hàng chỉ mua giám sát không nhận gì của Scanner.
Quyết định
- Một gói
accesshub-scanner(.deb,.tar.gz, sau này.rpm) chứa hai binary Go tĩnh của repo này và không khai báoDepends,RecommendshayConflictsvớiaccesshub-agent. Gói Agent cũng không tham chiếu gói Scanner. - Bộ đọc
accesshub-scanner(đã có): tài khoảnaccesshub-scanner, đúng một capabilityCAP_DAC_READ_SEARCH, không mạng (RestrictAddressFamilies=AF_UNIX,IPAddressDeny=any), chỉ ghi/var/lib/accesshub-scanner, chạy theo timer (Type=oneshot). Ghi báo cáo vào spool/var/lib/accesshub-scanner/spool(nhómaccesshub-scan-uploader, chỉ đọc). - Bộ gửi
accesshub-scan-uploader(mới,SCN-4): tài khoảnaccesshub-scan-uploader, không capability, chỉ HTTPS đi ra tới URL ingest của Scanner (RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX,ProtectSystem=strict,ProtectHome=yes, chỉ ghi/var/lib/accesshub-scan-uploader, đọc spool qua nhóm). Nó không đọc tệp nào ngoài spool và thư mục của mình, không mở cổng, không chạy lệnh, không giải nén body báo cáo. Dịch vụ thường trú nhỏ (MemoryMax=32M) hoặc timer mỗi 5 phút. - Danh tính và enroll riêng: quản trị viên tạo mã enroll Scanner trong Access Hub (một lần dùng, hết hạn, theo công ty, chỉ khi công ty có gói Scanner còn hạn mức). Chạy
accesshub-scan-uploader enroll --url <ingest> --token-file <tệp>trên máy. Bộ gửi sinh khóa riêng Ed25519 tại chỗ, gửi khóa công khai,machine_idbăm, hostname, phiên bản OS; ingest kiểm mã enroll với Access Hub, tạo bản ghi máy Scanner (scan_hosts:host_id,company_id,server_id, khóa công khai, trạng thái) và trảhost_id. Các lần gửi sau ký request bằng khóa riêng (hoặc đổi chữ ký lấy token phiên ngắn hạn), không có bí mật dùng chung lâu dài đi trên đường truyền. Khóa riêng0600trong thư mục của bộ gửi; bộ đọc không cần và không dùng nó. - Kiểm tra giấy phép: khi enroll và ở mỗi báo cáo, ingest kiểm công ty có tính năng
security_scanningvà máy nằm trong hạn mứcscan_hosts(hạn mức mới, không dùngmonitoring_agents). Hết hạn, thu hồi hoặc vượt hạn mức: 403licence_inactive; bộ gửi ngừng gửi, giữ spool, ghi trạng thái, thử lại thưa (6 giờ). Dedicated đọc hạn mức từDeploymentLicense. - Ingest phía máy chủ thuộc repo này: vai trò
ingestcủaaccesshub-secmatch(cùng binary, tiến trình riêng, đặt sau load balancer có TLS), endpointPOST /scan/v1/enroll,POST /scan/v1/report,GET /scan/v1/config. Ingest gắncompany_id,server_id,host_idtừ registry máy Scanner, rồi chuyểnForwardedReporttới vai trò matcher (POST /internal/v1/reports) qua outbox bền vững. Collector không tham gia. - Cấu hình quét: Access Hub, ingest (
GET /scan/v1/config, ETag), bộ gửi ghi nguyên tử/var/lib/accesshub-scan-uploader/config.pb, bộ đọc đọc và kiểm tra lại. Cấu hình chỉ bật tắt kiểm tra đã biên dịch và chỉnh ngưỡng số học. - Mã dùng chung chỉ bằng cách chép: mẫu enroll, lưu thông tin đăng nhập, backoff, WAL của repo Agent chỉ được chép vào
internal/của repo này (ghi nguồn và commit gốc ở đầu tệp), không import module Agent, không dùng chung tệp, socket, tài khoản, thông tin đăng nhập hay tiến trình lúc chạy. Mỗi repo tự sửa bản của mình.
Hệ quả
- Tiến trình đặc quyền không có mạng; tiến trình có mạng không đặc quyền. Chiếm ingest hoặc đường truyền chỉ chạm được bộ đọc qua một tệp cấu hình đã kiểm tra hai lần.
- Máy cài cả hai sản phẩm có hai danh tính:
agent_idcủa giám sát vàhost_idcủa Scanner, hai thông tin đăng nhập, hai lần enroll, hai luồng thu hồi. Access Hub gắn cả hai vào cùng bản ghiServer(khớpmachine_idbăm, hoặc người dùng chọn máy khi tạo mã enroll) để trang máy chủ hiển thị chung; thu hồi một bên không ảnh hưởng bên kia. - Việc ở repo Agent (
AGT-SEC-*) và Collector (COL-SEC-*) bị bỏ. Thay bằngSCN-4(bộ gửi),SMT-6(vai trò ingest),HUB-SEC-21(mã enroll, registry máy Scanner, hạn mứcscan_hosts, liên kếtServer). - Gói Scanner phải tự làm những gì Agent đã có: backoff, giới hạn tốc độ, xoay khóa, trạng thái, gỡ cài đặt sạch, tài liệu cài đặt riêng. Ước tính thêm khoảng 10 đến 14 ngày người so với phương án Agent chuyển tiếp.
- Kiểm tra cần mạng (TLS, P5) không nhờ Agent được: chạy trong bộ gửi, chỉ tới địa chỉ cục bộ của máy, chỉ các kiểu kiểm tra đã biên dịch.
- Bộ đọc và bộ gửi phát hành cùng gói nên luôn khớp nhau; với ingest nối bằng
schema_versioncủa báo cáo.
Phương án đã cân nhắc
| Phương án | Lý do không chọn |
|---|---|
| (a) Mô-đun trong Agent | Agent phải có quyền đọc mọi tệp trong khi có mạng; gắn hai sản phẩm vào nhau, trái Q25 |
| (b1) Một binary scanner vừa đọc vừa gửi | Tiến trình đặc quyền lại có mạng |
| (b2 cũ) Agent chuyển tiếp spool | Gắn Scanner vào Agent và Collector, trái Q25 |
| (c) Quét qua SSH từ trung tâm | Kết nối đi vào, trung tâm giữ thông tin đăng nhập mọi máy, chạy lệnh qua shell từ xa |
| Bộ gửi dùng chung thông tin đăng nhập của Agent khi có | Hai sản phẩm phụ thuộc nhau lúc chạy; thu hồi một bên làm hỏng bên kia |