Kiến trúc
Kiến trúc của Access Hub Scanner. Tài liệu này so sánh các phương án, nêu khuyến nghị và luồng dữ liệu. Quyết định chính thức ở ADR 0001 (thành phần trên máy), ADR 0002 (nơi so khớp), ADR 0008 (nơi lưu), ADR 0009 (quét nội dung có giới hạn), ADR 0010 (bộ máy phát hiện), ADR 0011 (finding nội dung không mang giá trị). Sơ đồ chi tiết ở architecture/.
1. Ràng buộc đầu vào (đã có trong hệ thống)
| Ràng buộc | Nguồn |
|---|---|
Access Hub Agent chạy bằng tài khoản accesshub-agent, CapabilityBoundingSet= rỗng, ProtectSystem=strict, ProtectHome=yes, MemoryMax=96M, CPUQuota=25% | access-hub-agent/internal/svc/accesshub-agent.service |
| Agent không thực thi lệnh từ xa, cấu hình từ xa chỉ theo lược đồ, khóa lạ bị bỏ | ADR 0005 của Agent, ADR 0003; ADR 0010 của Access Hub Collector |
Danh tính (company_id, server_id) chỉ lấy từ thông tin đăng nhập qua registry phía máy chủ, không tin payload (cùng nguyên tắc với giám sát) | Collector docs/03-protocol.md mục 1 |
| Giới hạn body 1 MiB nén, 8 MiB giải nén | Collector docs/03-protocol.md, bảng Giới hạn |
Mã enroll, transport, creds, WAL của Agent nằm trong internal/ nên repo khác không import được; Scanner chỉ được chép mẫu (ghi nguồn), không import | Cây access-hub-agent/internal/; quyết định Q25 |
| Scanner là sản phẩm, gói cước riêng; gói Scanner và gói Agent không phụ thuộc nhau theo chiều nào | Quyết định chủ dự án Q25 (2026-10-02), ADR 0001 |
Access Hub là nguồn sự thật cho dữ liệu nghiệp vụ (Server là thực thể chung của cả giám sát và Scanner) | ADR 0004 của Collector |
2. Phương án thành phần trên máy
(a) Mô-đun trong Agent hiện có
Thêm bộ thu security vào accesshub-agent.
| Ưu | Nhược |
|---|---|
| Một gói cài, một danh tính, dùng lại WAL, transport, enroll, cấu hình từ xa | Kiểm tra cấu hình cần đọc /etc/shadow, /etc/sudoers, khóa host SSH (quyền và chủ sở hữu): Agent phải lên root hoặc có CAP_DAC_READ_SEARCH thường trực, trong khi nó là tiến trình có mạng và nhận cấu hình từ xa. Phá nguyên tắc chạy không đặc quyền (ANFR-13 của Agent) |
| Không cần thay đổi giao thức enroll | Ngân sách Agent (50 MB RSS, MemoryMax=96M) không chứa nổi đỉnh khi duyệt tệp và đọc rpmdb |
| Gắn nhịp phát hành: sửa một kiểm tra phải phát hành lại Agent trên mọi máy | |
| Một lỗi parser (tệp cấu hình do kẻ tấn công cục bộ cài) chạy trong tiến trình có mạng |
(b) Binary scanner riêng
(b1) Scanner riêng có mạng, dùng chung thư viện enroll và transport. Scanner tự enroll (License riêng hoặc dùng lại token của Agent), tự gửi tới Collector.
| Ưu | Nhược |
|---|---|
| Tách nhịp phát hành, tách ngân sách tài nguyên | Thư viện cần dùng chung đang ở internal/ của Agent: phải tách ra module công khai (pkg/), thay đổi repo Agent |
| Có thể cài scanner mà không cần Agent | Tiến trình đặc quyền đọc lại có mạng, xử lý phản hồi và cấu hình từ xa: bề mặt tấn công giống (a) |
Danh tính thứ hai: hoặc License riêng (đếm vào monitoring_agents của gói, thêm bản ghi, thêm xoay token), hoặc đọc credentials.json của Agent (ràng buộc định dạng tệp, hai tiến trình dùng chung token và giới hạn tốc độ) | |
| Hai WAL, hai bộ backoff, hai đường TLS trên mỗi máy |
(b2) Scanner riêng không có mạng, Agent chuyển tiếp (tách đặc quyền). Bộ đọc không mạng ghi spool, Agent đọc spool và gửi tới Collector bằng token của nó. Đây là khuyến nghị ban đầu; bị loại bởi quyết định Q25: gắn Scanner vào Agent và Collector, không cài được Scanner nếu không có giám sát.
(b3) Gói Scanner có bộ đọc không mạng và bộ gửi riêng không đặc quyền (tách đặc quyền trong cùng gói). Bộ đọc accesshub-scanner chạy theo timer bằng tài khoản có đúng CAP_DAC_READ_SEARCH, mạng bị chặn ở systemd, ghi báo cáo protobuf nén vào spool. Bộ gửi accesshub-scan-uploader (tài khoản riêng, không capability, chỉ HTTPS đi ra) có danh tính Scanner riêng (enroll bằng mã enroll Scanner, khóa Ed25519 sinh tại máy), đọc spool qua nhóm và gửi tới vai trò ingest của secmatch. Cấu hình quét đi ngược: ingest, bộ gửi ghi config.pb, bộ đọc đọc và kiểm tra lại.
| Ưu | Nhược |
|---|---|
| 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 hay đường truyền không chạm được tiến trình đặc quyền ngoài một tệp cấu hình đã kiểm tra hai lần | Danh tính thứ hai trên máy cài cả giám sát và Scanner (agent_id và host_id), hai enroll, hai luồng thu hồi |
| Scanner độc lập hoàn toàn với giám sát: bán, cài, gỡ, nâng cấp riêng (Q25) | Phải tự làm enroll, backoff, xoay khóa, trạng thái (chép mẫu từ Agent): khoảng 10 đến 14 ngày người |
| Không cần thay đổi repo Agent hay Collector | Cần vai trò ingest có TLS, giới hạn, registry máy Scanner ở trung tâm (SMT-6, HUB-SEC-21) |
| Bộ đọc nhỏ: không TLS, không enroll, không backoff; bộ đọc và bộ gửi cùng gói nên luôn khớp phiên bản | Kiểm tra TLS cục bộ (P5) chạy trong bộ gửi, chỉ tới địa chỉ của chính máy |
| Bộ đọc không thường trú: RSS bằng 0 giữa hai lần quét |
| | Máy sau NAT, tường lửa không với tới được; Dedicated cần thêm vùng mạng |
So sánh
| Tiêu chí | (a) | (b1) | (b2) | (b3) | (c) |
|---|---|---|---|---|---|
| Đặc quyền và mạng cùng một tiến trình | Có | Có | Không | Không | Có (phía trung tâm) |
| Chỉ đi ra | Có | Có | Có | Có | Không |
| Thực thi từ xa | Không | Không | Không | Không | Có (lệnh qua SSH) |
| Phụ thuộc Agent | Có | Có (thư viện) | Có | Không | Không |
| Danh tính mới | Không | Có | Không | Có (host_id) | Thông tin đăng nhập SSH |
| Thay đổi repo Agent | Lớn | Lớn (tách thư viện) | Vừa | Không | Không |
| Ngân sách RAM trên máy | Vượt ngân sách Agent | Riêng | Riêng, 0 khi rảnh | Bộ đọc 0 khi rảnh, bộ gửi dưới 32 MB | 0 |
| Cài đặt | Một gói | Một hoặc hai gói | Hai gói | Một gói Scanner | Không |
Khuyến nghị
(b3), đã chấp nhận ở ADR 0001 (Q1, Q6, Q25). Đây là cách duy nhất vừa giữ ba ràng buộc (không đặc quyền khi có mạng, chỉ đi ra, không thực thi từ xa) trong khi đọc được tệp chỉ root đọc, vừa để Scanner độc lập với giám sát. (c) chỉ cân nhắc sau P10 cho thiết bị không cài được gì, cần ADR mới (Q27).
3. Nơi so khớp: trên máy hay tập trung
| Tiêu chí | Trên máy | Tập trung (secmatch) |
|---|---|---|
| Kích thước DB trên máy | Hàng trăm MB và tải mỗi ngày trên mọi máy (ví dụ DB của Trivy, Grype cỡ hàng trăm MB, cần đo ở spike S2) | 0 |
| Ngân sách CPU, RAM, mạng trên máy | Vượt xa SNFR-03, SNFR-04 | Inventory vài chục KB |
| CVE mới công bố | Phải quét lại mọi máy | So khớp lại inventory đã lưu, không chạm máy |
| Dedicated offline | Phải phân phối DB tới từng máy | Chỉ nhập DB vào secmatch on-prem |
| Nhất quán | Mỗi máy có thể có DB khác ngày | Một DB, một phiên bản cho cả công ty |
| Tìm "máy nào có gói X" | Không làm được nếu không gửi inventory | Có sẵn |
| Lộ thông tin | Không gửi danh sách gói ra ngoài máy | Danh sách gói rời máy (siêu dữ liệu vận hành, lưu có cô lập tenant) |
Khuyến nghị: tập trung (ADR 0002). Máy chỉ gửi inventory và kết quả kiểm tra cấu hình. Đánh giá kiểm tra cấu hình vẫn diễn ra trên máy (cần đọc tệp), chỉ phần so với danh sách dự kiến (cổng nghe) diễn ra tập trung.
3b. Phát hiện bí mật và dữ liệu cá nhân: luôn trên máy
Ngược với so khớp lỗ hổng, phát hiện nội dung không có phương án tập trung: muốn quét ở trung tâm thì phải gửi nội dung tệp ra khỏi máy, trái yêu cầu cứng "giá trị không rời máy" (ADR 0011). Vì vậy:
| Phần | Nơi chạy | Lý do |
|---|---|---|
| Duyệt, lọc, đọc tệp, chạy detector, che giấu, tính fingerprint | Scanner trên máy (lượt nội dung) | Giá trị chỉ tồn tại trong bộ nhớ của scanner |
| Chỉ mục tệp đầy đủ, trạng thái từng tệp | Máy (/var/lib/accesshub-scanner/index/) | Danh sách mọi tệp không rời máy (14 mục 6) |
| So sánh trạng thái finding nội dung giữa hai báo cáo, phát sự kiện | Secmatch | Dùng chung outbox, idempotency, xóa theo công ty với finding lỗ hổng |
| Vòng đời (SLA, ngoại lệ, quyền xem, audit, thông báo) | Access Hub | Như mọi finding (ADR 0008) |
Sinh và giữ K_company (mã hóa ENC-2) | Access Hub | Bí mật theo công ty; phát xuống máy qua cấu hình |
Hệ quả cho tài nguyên trên máy: lượt nội dung là phần tốn nhất của sản phẩm, nên tách unit, chạy trong khung giờ yên tĩnh, tăng dần, có ngân sách riêng (ADR 0009, SNFR-12 đến SNFR-19).
4. Thành phần
| Thành phần | Repo | Vai trò |
|---|---|---|
accesshub-scanner | Repo này, cmd/accesshub-scanner | Binary Go tĩnh trên máy, hai unit cùng binary: lượt siêu dữ liệu mỗi giờ (DB gói, os-release, kernel, dịch vụ, phần mềm, tệp cấu hình, /proc, kiểm tra AHS-*) và lượt nội dung trong khung giờ yên tĩnh (detector AHK-*, AHP-*, chỉ mục cục bộ). Ghi báo cáo vào spool; không mạng |
accesshub-scan-uploader | Repo này (SCN-4), cùng gói | Bộ gửi trên máy, không đặc quyền: enroll, giữ khóa Ed25519 của máy Scanner, đọc spool, gửi POST /scan/v1/report, tải GET /scan/v1/config ghi config.pb, chạy kiểm tra TLS cục bộ (P5). Không phụ thuộc Agent |
Secmatch vai trò ingest | Repo này (SMT-6), accesshub-secmatch --role ingest | Điểm vào công khai của Scanner sau load balancer: enroll, xác thực chữ ký máy Scanner, kiểm giấy phép (security_scanning, hạn mức scan_hosts), giới hạn, khử trùng, gắn company_id, server_id, host_id từ registry, chuyển tiếp tới vai trò matcher qua outbox bền vững |
accesshub-secmatch vai trò matcher | Repo này, cmd/accesshub-secmatch | Dịch vụ Go trung tâm, mạng nội bộ: lưu inventory mới nhất mỗi máy (gói, dịch vụ, phần mềm, thống kê tệp), so khớp, tính điểm, so khớp lại khi DB đổi, so sánh trạng thái finding nội dung, gửi delta finding về Access Hub, API nội bộ tra cứu gói, phần mềm, dịch vụ |
secdb-build | Repo này, cmd/secdb-build | Job dựng DB: tải nguồn (03), chuẩn hóa, ký Ed25519, phát hành. Chạy ở hạ tầng của nền tảng, không chạy ở máy khách |
| Access Hub (mở rộng) | /var/www/access-hub | Finding và vòng đời (lỗ hổng, cấu hình, bí mật, dữ liệu cá nhân), ngoại lệ, SLA, dashboard, thông báo, quyền (gồm quyền xem bí mật và dữ liệu cá nhân), cài đặt quét nội dung, K_company, mã enroll và registry máy Scanner (HUB-SEC-21), gói và hạn mức, thống kê nền tảng ẩn danh |
Vị trí của secmatch: dịch vụ riêng trong repo này (Q3, đã duyệt), gồm hai vai trò cùng binary: ingest (công khai, nhẹ, không giữ DB lỗ hổng) và matcher (nội bộ, giữ DB và kho inventory). Collector không tham gia đường Scanner.
5. Luồng dữ liệu
5.1 Quét và gửi (đường chính)
accesshub-scanner.timerkích hoạt mỗi giờ (lệch ngẫu nhiên). Scanner somtime, kích thước DB gói với lần trước (lưu trong thư mục trạng thái của scanner). Không đổi và chưa đến hạn 24 giờ thì thoát.- Bộ đọc đọc tệp cấu hình quét do bộ gửi ghi (
/var/lib/accesshub-scan-uploader/config.pb), kiểm tra lại lược đồ, bỏ khóa lạ. Không có tệp thì dùng mặc định cục bộ. - Scanner kiểm kê, chạy kiểm tra cấu hình đến hạn, dựng
SecurityReport(xem07), tínhinventory_hash, nén, ghi nguyên tử vào/var/lib/accesshub-scanner/spool/(tệp tạm,fsync, đổi tên). Giữ tối đa 2 báo cáo, báo cáo mới thay báo cáo cũ chưa gửi. - Bộ gửi
accesshub-scan-uploaderkiểm tra spool mỗi 60 giây (chỉreaddir, rất rẻ), lấy báo cáo mới nhất chưa gửi, kiểm tra khung (magic,schema_versionnằm trong miền, kích thước, SHA-256), gửiPOST /scan/v1/reportký bằng khóa của máy Scanner. Nếuinventory_hashtrùng lần đã được xác nhận và kiểm tra cấu hình không đổi, bộ gửi gửi dạng rút gọn (chỉ băm). - Vai trò ingest xác thực chữ ký, tra registry máy Scanner (
host_id,company_id,server_id), kiểm giấy phép (403licence_inactivekhi hết gói hoặc vượt hạn mứcscan_hosts), áp giới hạn, ghi outbox, trả 202. Bộ gửi ghireport_idđã xác nhận vào trạng thái của mình. - Ingest chuyển tiếp
ForwardedReporttới vai trò matcherPOST /internal/v1/reports. Matcher lưu inventory theo(company_id, server_id), so khớp, so với finding đang mở của máy, đưa delta (mở, đóng, đổi điểm) vào outbox. - Secmatch gửi lô delta tới Access Hub
POST /api/v1/security/matcher/findings(idempotent theoevent_id). Access Hub cập nhậtsecurity_findings, kích hoạt thông báo theo luật.
5.2 DB lỗ hổng cập nhật (không cần máy)
secdb-buildchạy hằng ngày (và khi KEV đổi), phát hành gói DB ký số kèm manifest.- Secmatch kéo manifest, xác minh chữ ký và số phiên bản tăng, nạp DB mới song song với DB cũ, chuyển nguyên tử.
- Secmatch so khớp lại mọi inventory đã lưu theo từng công ty, chỉ phát delta. Làm giàu EPSS và KEV cũng đi theo đường này (điểm đổi thì phát
finding.rescored).
5.3 Người dùng xem
Access Hub đọc security_findings (của mình) cho danh sách, dashboard. Tra cứu gói ("máy nào có gói X") gọi API nội bộ của secmatch với company_id lấy từ phiên người dùng, giống mẫu MonitoringCollectorClient hiện có (app/Services/Monitoring/Collector/MonitoringCollectorClient.php).
5.4 Xóa
Xóa vĩnh viễn Server hoặc purge Company: Access Hub xóa bảng security_* của phạm vi đó trong cùng giao dịch, sau commit gọi DELETE /internal/v1/companies/{id}/data hoặc .../servers/{id}/data của secmatch (giống HUB-14, Collector docs/06 mục 8.1).
5.5 Lượt nội dung (khung giờ yên tĩnh)
accesshub-scanner-content.timerkích hoạt trong khung giờ yên tĩnh (mặc định 01:00 đến 05:00 giờ máy, lệch ngẫu nhiên). Scanner đọcconfig.pbvà/etc/accesshub-scanner/local.conf, tính phạm vi hiệu lực (ADR 0009 mục 2), nạpK_hostvàK_company.- Duyệt từ điểm dừng của lượt trước, so từng tệp với chỉ mục; tệp đổi hoặc chưa quét được lọc (loại, kích thước, nhị phân), đọc theo luồng, chạy detector, che giấu, tính fingerprint, ghi kết quả vào chỉ mục (không giá trị).
- Trước mỗi lô tệp kiểm tra PSI, ngân sách CPU, byte, số mục và giờ kết thúc khung; vượt thì lưu điểm dừng và thoát.
- Cuối lượt (hoặc ở lượt siêu dữ liệu kế tiếp), scanner dựng
SecurityReportv2 gồm inventory mới nhất và ảnh chụp đầy đủ finding nội dung từ chỉ mục, kèm độ phủ;content_hashkhông đổi thì chỉ gửi băm. - Từ bộ gửi trở đi đi chung đường 5.1: ingest kiểm tra lớp hai phần nội dung (
07mục 3.4), secmatch so trạng thái, phátfinding.opened,finding.updated,finding.resolvedvớikindlàsecrethoặcsensitive_data.
6. Topology
| Môi trường | Bố trí |
|---|---|
| Dev | Một secmatch chạy cả hai vai trò, kho inventory bằng tệp, DB lỗ hổng nạp từ tệp, bộ gửi trỏ tới ingest cục bộ |
| Cloud | Ingest 2 bản sau load balancer có TLS (tên miền riêng của Scanner), matcher 2 bản sau load balancer nội bộ, kho inventory MySQL riêng (không dùng chung MySQL của Access Hub), một tiến trình giữ lease chạy so khớp lại, secdb-build chạy như job định kỳ ở hạ tầng nền tảng |
| Dedicated | Một secmatch on-prem (hai vai trò) cạnh Access Hub của khách hàng, không cần Collector, DB kéo từ CDN của nền tảng (chỉ đi ra) hoặc nhập tay khi không có Internet (P10) |
7. Công nghệ
| Lớp | Lựa chọn đề xuất | Lý do |
|---|---|---|
| Ngôn ngữ bộ đọc, bộ gửi, secmatch, secdb-build | Go, không CGO | Giống Agent, Collector (ADR 0001 của Agent, ADR 0003 của Collector); .proto của Scanner thuộc repo này (accesshub.scan.v1) |
| Đọc rpmdb | Thư viện Go thuần (ứng viên github.com/knqyf263/go-rpmdb, giấy phép cần xác nhận ở P0) | Tránh gọi rpm, tránh CGO. Spike S1 đo kích thước và độ đúng |
| So sánh phiên bản | Tự viết theo đặc tả dpkg, rpmvercmp, apk, kiểm thử bằng bảng lấy từ công cụ gốc | Lõi độ chính xác, phải nắm hoàn toàn (ADR 0007) |
| Kho inventory của secmatch | MySQL (cùng loại máy chủ đội đã vận hành) hoặc PostgreSQL | Q4 |
| Định dạng DB lỗ hổng | Tệp nhị phân hoặc SQLite thuần Go chỉ đọc, đóng gói tar.zst kèm manifest ký | ADR 0005, spike S2 |
| Giao thức | HTTPS + protobuf, cùng kiểu với đường Agent tới Collector nhưng endpoint, danh tính và hợp đồng riêng của Scanner | ADR 0002 của Collector (tham khảo), ADR 0001 |
| Bộ máy phát hiện | regexp của Go (RE2), Aho-Corasick tự viết hoặc thư viện giấy phép dễ dãi, bộ xác thực tự viết; quy tắc bí mật khởi đầu từ cấu hình gitleaks (MIT) | ADR 0010, spike S6, S7 |
| Chỉ mục cục bộ | bbolt (MIT) hoặc định dạng tự viết | ADR 0009, spike S6 |
| Fingerprint | HMAC-SHA256 thư viện chuẩn của Go | ADR 0011 |