L2 - Monitoring Platform - Agent - Software Architecture Document (SAD)
Front matter
| Trường | Giá trị |
|---|---|
| Tên trang | L2 - Monitoring Platform - Agent - SAD |
| Status | BẢN NHÁP (tài liệu chưa sẵn sàng trình thẩm định) |
| Version & Change Log | v0.1, 2026-09-30: bản nháp đầu tiên, dựng từ mã nguồn internal/**, packaging/**, scripts/**, .gitlab-ci.yml, docs/00 đến docs/10, ADR 0001 đến 0005 của Agent và hợp đồng Agent - Collector ở docs/10-wire-contract.md. Bản này đã bỏ mọi tham chiếu sang repo khác, L1 là tài liệu cùng thư mục |
| Owner | chưa chỉ định (cần một tác giả duy nhất chịu trách nhiệm) |
| Reviewers / Approvers | chưa chỉ định. Chưa ai sign-off. Không mục nào được ghi APPROVED |
| L1 Document | L1 - Giám sát máy chủ - Access Hub Agent. Mục L1 được truy vết: mục 2 (Mục tiêu 2, 5, 6), mục 3 (KPI công nghệ: T1, T2, T5, T7), mục 4 (Quality Attribute), mục 6 (Solution Overview), mục 7 (System Context), mục 8 (Assumptions, Constraints), mục 10 (Rủi ro, câu hỏi mở), mục 11 (Phasing), mục 12 (Cấp độ quan trọng) |
| L3 Documents | L3 Collectors, L3 WAL và Sender, L3 Enroll, Credentials, Config, L3 Service và Packaging |
| L2 anh em | L2 Collector, L2 Access Hub (do luồng công việc khác viết, tên tệp chốt sau) |
| Referenced standards | STD-DIAG v1.1 (Danh Mục - Tiêu Chuẩn Diagram), Danh Mục - Tiêu Chuẩn Thiết Kế Kiến Trúc v1.0, mẫu Tài liệu L2 - Thiết kế chi tiết kiến trúc (SAD), HD - Quy tắc Tách và Cập nhật Tài liệu L1 - L2 - L3 |
| Last reviewed | 2026-09-30 (đối chiếu với mã tại commit a23f929 cộng các thay đổi chưa commit của AGT-6) |
| System Tier | Đề xuất, chưa xác nhận: Cấp độ 3, Business Operational, kế thừa đề xuất của L1 mục 12 (OQ-7 của L1). Xem mục 14 |
| Mục lục | 1 Mục tiêu và phạm vi, 2 Kiến trúc tổng quan, 3 Yêu cầu chức năng, 4 Yêu cầu phi chức năng, 5 Công nghệ, 6 Kiến trúc tích hợp, 7 Kiến trúc dữ liệu, 8 Luồng nghiệp vụ, 9 Bảo mật, 10 Triển khai, 11 Chi phí và dung lượng, 12 Mở rộng và độ tin cậy, 13 Quan sát, 14 Sẵn sàng vận hành, 15 Kiểm thử, 16 Rủi ro, A Thuật ngữ, B Tham chiếu |
Truy vết: L3 (4 tệp trên) -> L2 này (mục 2.3, 3, 4, 6) -> L1 (mục tiêu 2, 5, 6 và KPI công nghệ T1, T2, T5, T7).
Quy ước nhãn trạng thái dùng xuyên suốt
| Nhãn | Nghĩa |
|---|---|
| ĐÃ HIỆN THỰC | Đã xác minh trong mã, kèm đường dẫn tệp |
| THIẾT KẾ, CHƯA XÂY | Có trong tài liệu thiết kế (docs/*, ADR), chưa có mã. Không được đọc như hiện trạng |
| MỘT PHẦN | Có mã nhưng chưa đủ tiêu chí nghiệm thu (ví dụ AGT-6) |
| ĐỀ XUẤT | Đề xuất của tài liệu này, chưa được chủ hệ thống quyết định |
Quy tắc xử lý sai lệch: khi mã và tài liệu thiết kế khác nhau, mã thắng và sai lệch được ghi ở mục 16.2 (Debt ID D-01 đến D-13).
1. Business Objectives & Scope
Agent là chương trình nhỏ chạy trên từng máy chủ được giám sát. Nó thu thập chỉ số nền tảng (CPU, RAM, swap, đĩa, mạng, tải, uptime), gom thành lô protobuf và đẩy ra ngoài qua HTTPS tới Collector. Agent chỉ gọi ra (outbound-only), chỉ gửi giá trị gauge, không mở cổng, không nhận lệnh thực thi. Khi mất kết nối, agent đệm lô xuống đĩa (WAL) và gửi bù khi có mạng.
Mục tiêu L1 mà L2 này phục vụ (L1 mục 2): mục tiêu 2 (thu thập số liệu nền tảng), mục tiêu 5 (cô lập dữ liệu giữa các công ty, phía agent thể hiện bằng việc không bao giờ tự gán company_id, server_id), mục tiêu 6 (triển khai và vận hành agent hàng loạt dễ dàng, an toàn).
1.1 In Scope
| STT | Hạng mục | Trạng thái |
|---|---|---|
| 1 | Thu thập chỉ số host Linux từ /proc và statfs: cpu, memory, swap, disk, net, uptime | ĐÃ HIỆN THỰC (internal/collector/linux) |
| 2 | Chỉ số tự thân agent_* | ĐÃ HIỆN THỰC (internal/collector/linux/self.go) |
| 3 | Chuẩn hóa mẫu, danh sách trắng tên và nhãn, giới hạn 500 series | ĐÃ HIỆN THỰC (internal/collector/engine.go, catalog.go) |
| 4 | Enroll bằng License, lưu thông tin đăng nhập 0600, ràng buộc machine_id | ĐÃ HIỆN THỰC (internal/enroll, internal/creds) |
| 5 | Đóng lô, gửi định kỳ có phân pha, heartbeat lô rỗng, backoff full jitter, xử lý bảng mã trạng thái | ĐÃ HIỆN THỰC (internal/sender, internal/backoff, internal/transport) |
| 6 | WAL trên đĩa, giới hạn dung lượng và tuổi, phục hồi sau mất điện, gửi bù có giới hạn | ĐÃ HIỆN THỰC (internal/buffer) |
| 7 | Cấu hình cục bộ YAML nghiêm ngặt, biến môi trường AH_*, cờ dòng lệnh, nạp lại bằng SIGHUP | ĐÃ HIỆN THỰC (internal/config, internal/cli/run.go) |
| 8 | CLI: run, enroll, version, check-config, collect-once, service, uninstall | ĐÃ HIỆN THỰC (internal/cli) |
| 9 | Dịch vụ systemd có hardening, gói .deb .rpm (nfpm), install.sh xác minh checksum và chữ ký | MỘT PHẦN (AGT-6, chưa commit, chưa thử trên ma trận distro thật) |
| 10 | Bộ thu Windows (API trực tiếp), dịch vụ Windows, MSI, DPAPI | Bộ thu và dịch vụ (internal/winsvc, ADR 0008) ĐÃ XÂY, chưa chạy trên Windows thật (AGT-7, ADR 0007). MSI, DPAPI: CHƯA XÂY |
| 11 | Checks: service, port, tcp, http, cert | ĐÃ XÂY (AGT-8, internal/collector/checks). Windows: đủ 5 kiểu, service qua SCM, port qua bảng TCP/UDP của hệ điều hành (chưa chạy trên Windows thật) |
| 12 | Kiểm kê (/inventory) | ĐÃ XÂY (AGT-9, internal/inventory): gửi khi khởi động, khi đổi, mỗi 6 giờ. Phần mềm cài đặt không thu |
| 13 | Xoay token, cấu hình từ xa ETag, status, diag | ĐÃ XÂY (AGT-10): cấu hình từ xa, status, diag, hiệu chỉnh đồng hồ, xoay token (agent xong, chờ Access Hub có endpoint renew để chạy thật) |
| 14 | Ký gói, kho gói, cập nhật tự động, mTLS | THIẾT KẾ, CHƯA XÂY (AGT-11 đến AGT-13) |
1.2 Out of Scope
| Hạng mục | Thuộc về | Ghi chú |
|---|---|---|
| Nhận, xác thực, lưu và cảnh báo trên số liệu | Collector (L2 Collector) | Agent chỉ là nguồn đẩy |
| Phát hành License, vòng đời agent, hiển thị trên giao diện | Access Hub (L2 Access Hub) | Agent chỉ dùng token |
| Thu thập log, APM, tracing, giám sát không cần agent | Ngoài phạm vi (Phi mục tiêu L1 mục 2) | Giai đoạn 4 |
| Thực thi lệnh từ xa | Cố ý không làm (ADR 0005) | Không có mã, cấu hình từ xa không chứa lệnh hay đường dẫn |
| Container, Kubernetes, Windows Server 2012 R2 trở xuống | Chưa quyết định (OQ-3 của L1) | |
| Ứng dụng di động | Ngoài phạm vi của agent | Thuộc Access Hub |
| Lưu trữ dài hạn số liệu | Collector (VictoriaMetrics) | Agent chỉ giữ tối đa 24 giờ trong WAL |
2. Architecture Overview & Principles
2.1 Kiểu kiến trúc
Agent là một tiến trình Go đơn, tĩnh (CGO_ENABLED=0, -trimpath), dạng vòng lặp thu thập và đẩy (collect-and-push loop) với bộ đệm store-and-forward trên đĩa. Mô-đun module Go: gitlab.com/thienpn2/access-hub-agent, ranh giới bằng package dưới internal/. Không có dịch vụ con, không có IPC, không có cổng lắng nghe.
2.2 Nguyên tắc
| # | Nguyên tắc | Hệ quả thiết kế | Nguồn |
|---|---|---|---|
| P1 | Chỉ gọi ra, không lắng nghe | Không mở cổng. Điều khiển chỉ qua tín hiệu OS và CLI cục bộ | ANFR-08, internal/transport |
| P2 | Không thực thi mã từ xa | Không có bộ thực thi lệnh. Cấu hình từ xa (khi có) chỉ chứa khóa cho phép | ADR 0005, ADR 0003 |
| P3 | Không mất mẫu vì lỗi mạng, chỉ mất khi vượt giới hạn tường minh | WAL trên đĩa, giới hạn 50 MiB và 24 giờ, đếm mẫu rơi | ADR 0002, internal/buffer/wal.go |
| P4 | Chi phí tài nguyên bị chặn cứng | Budget CPU, RSS, kích thước, số series, giới hạn systemd | docs/02, scripts/cross-build.sh, agent.service |
| P5 | Cô lập lỗi | Mỗi bộ thu chạy trong safeCollect có recover panic. Lỗi thu không dừng agent | internal/collector/engine.go |
| P6 | Cấu hình sai thì giữ cấu hình cũ | Nạp lại thất bại chỉ ghi log. Khởi động với cấu hình sai thoát mã 3 | internal/cli/run.go |
| P7 | Bí mật không rời khỏi tiến trình dạng rõ | Token che trong log và String(). Tệp thông tin đăng nhập 0600, ghi nguyên tử | internal/creds, internal/logx |
| P8 | Mã thắng tài liệu | Sai lệch ghi tường minh (mục 16.2) | HD Tách và Cập nhật L1-L2-L3 |
2.3 Thành phần và truy vết L3
| Mã | Thành phần | Package chính | L3 chịu trách nhiệm |
|---|---|---|---|
| CMP-1 | Runtime Core (vòng lặp, tín hiệu, log, thống kê) | internal/agent, internal/cli/run.go, internal/logx, internal/stats | Chưa có L3 riêng. Vòng cycle được mô tả trong L3 WAL và Sender, nạp lại cấu hình trong L3 Enroll, Credentials, Config (xem D-14 ở 16.2) |
| CMP-2 | Collector Engine | internal/collector, +host, +linux | L3 Collectors |
| CMP-3 | WAL Buffer | internal/buffer | L3 WAL và Sender |
| CMP-4 | Sender và Backoff | internal/sender, internal/backoff | L3 WAL và Sender |
| CMP-5 | Transport Client | internal/transport, internal/wire | L3 WAL và Sender |
| CMP-6 | Enroll và Credentials | internal/enroll, internal/creds, internal/hostinfo | L3 Enroll, Credentials, Config |
| CMP-7 | Config Loader | internal/config | L3 Enroll, Credentials, Config |
| CMP-8 | Service và Packaging | internal/svc, internal/cli/service.go, packaging/, scripts/ | L3 Service và Packaging |
2.4 Bản đồ ngữ cảnh (Context Map)
flowchart LR
classDef bc fill:#1f3a5f,stroke:#4a90d9,color:#fff
classDef entity fill:#3a3320,stroke:#d9b84a,color:#fff
classDef infra fill:#444,stroke:#aaa,color:#fff
SA(["Quản trị viên máy chủ"]):::entity
AHA(["Quản trị viên Access Hub"]):::entity
HOST(["Hệ điều hành máy chủ"]):::infra
REPO(["Nơi phát hành gói"]):::infra
COL(["Collector"]):::bc
subgraph AGT["Hệ thống Agent"]
AG["Agent trên máy chủ"]:::bc
end
AHA -.->|"cấp License"| SA
SA -->|"cài đặt và cấu hình"| AG
HOST -->|"cung cấp số liệu thô"| AG
REPO -.->|"phát hành gói cài"| SA
AG -->|"đẩy lô số liệu"| COL
COL -->|"trả ack và mã trạng thái"| AGChú giải: nét liền là tương tác đồng bộ (request và response hoặc thao tác trực tiếp), nét đứt là bất đồng bộ hoặc ngoài băng. Bảng quan hệ:
| Chiều | Bên | Nội dung | Giao thức, bảo đảm |
|---|---|---|---|
| Agent tới Collector | Collector | Enroll, đẩy lô, kiểm tra kết nối (/ping), kéo cấu hình (chỉ khi thăm dò 401) | HTTPS TLS 1.2+, protobuf, /agent/v1. Chi tiết mục 6.2 |
| Collector tới Agent | Collector | Ack, mã lỗi, config_etag, server_time_ms | Phản hồi của cùng kết nối, không có kết nối vào agent |
| OS tới Agent | Hệ điều hành | /proc/stat, /proc/meminfo, /proc/diskstats... và statfs | Đọc tệp cục bộ, chỉ đọc |
| Quản trị viên tới Agent | Quản trị viên máy chủ | enroll, service install, agent.yaml, SIGHUP | CLI cục bộ, cần quyền phù hợp |
| Access Hub tới quản trị viên | Access Hub | License dùng một lần | Ngoài băng (người chuyển token vào tệp hoặc stdin) |
| Nơi phát hành tới quản trị viên | Kho gói | .deb, .rpm, .tar.gz, SHA256SUMS, chữ ký | HTTPS hoặc file://. Kho thật chưa có (Q2) |
3. Functional Requirements
Mã AFR lấy từ docs/02-requirements.md của Agent. Cột L3 cho biết nơi đặc tả chi tiết.
| STT | Nhóm | Mô tả | Mã gốc | Trạng thái | L3 |
|---|---|---|---|---|---|
| FR-01 | Danh tính | Enroll bằng License, nhận agent_id và agent_token, ràng buộc machine_id băm | AFR-01, AFR-02, AFR-05 | ĐÃ HIỆN THỰC | Enroll, Credentials, Config |
| FR-02 | Danh tính | Lưu thông tin đăng nhập 0600, ghi nguyên tử, từ chối tệp quyền rộng | AFR-03 | ĐÃ HIỆN THỰC (Linux). Windows DPAPI THIẾT KẾ, CHƯA XÂY | Enroll, Credentials, Config |
| FR-03 | Danh tính | Dừng gửi khi machine_id khác lúc enroll (identity_mismatch) | AFR-05 (liên quan) | ĐÃ HIỆN THỰC (internal/agent/agent.go) | Enroll, Credentials, Config |
| FR-04 | Thu thập | Thu cpu, memory, swap, disk, net, uptime trên Linux từ /proc | AFR-10 đến AFR-14 | ĐÃ HIỆN THỰC | Collectors |
| FR-05 | Thu thập | Chỉ số tự thân agent_* | AFR-18 | ĐÃ HIỆN THỰC | Collectors |
| FR-06 | Thu thập | Danh sách trắng tên và nhãn, giới hạn series, cắt nhãn | AFR-19 | ĐÃ HIỆN THỰC | Collectors |
| FR-07 | Thu thập | Bật tắt từng bộ thu, lọc mount và giao diện bằng regex RE2 | AFR-12, AFR-13 | ĐÃ HIỆN THỰC (cấu hình cục bộ) | Collectors, Enroll Credentials Config |
| FR-08 | Truyền | Gửi lô định kỳ, phân pha theo agent_id, nén, protobuf, heartbeat lô rỗng | AFR-20, AFR-24 | ĐÃ HIỆN THỰC (nén gzip trên dây) | WAL và Sender |
| FR-09 | Truyền | Backoff full jitter, tôn trọng Retry-After, xử lý đúng từng mã trạng thái | AFR-21 | ĐÃ HIỆN THỰC | WAL và Sender |
| FR-10 | Độ bền | WAL đĩa, giới hạn dung lượng và tuổi, phục hồi sau mất điện | AFR-22 | ĐÃ HIỆN THỰC | WAL và Sender |
| FR-11 | Độ bền | Gửi bù có giới hạn tốc độ (catch_up_batches) | AFR-23 | ĐÃ HIỆN THỰC | WAL và Sender |
| FR-12 | Truyền | Ghi độ lệch đồng hồ từ server_time_ms | AFR-25 | ĐÃ HIỆN THỰC (chỉ ghi và báo, chưa hiệu chỉnh mẫu) | WAL và Sender |
| FR-13 | Truyền | Xác minh TLS bắt buộc, ghim CA tùy chọn, proxy | AFR-26 | ĐÃ HIỆN THỰC | WAL và Sender |
| FR-14 | Cấu hình | Cấu hình YAML nghiêm ngặt, check-config, thứ tự cờ > env > tệp > mặc định | AFR-30 | ĐÃ HIỆN THỰC | Enroll, Credentials, Config |
| FR-15 | Cấu hình | Nạp lại cấu hình cục bộ bằng SIGHUP, giữ cấu hình cũ nếu sai | AFR-30 | ĐÃ HIỆN THỰC | Enroll, Credentials, Config |
| FR-16 | Điều khiển | CLI run, enroll, version, check-config, collect-once | AFR-34 (một phần) | ĐÃ HIỆN THỰC | Enroll, Credentials, Config |
| FR-17 | Điều khiển | status, diag | AFR-34 | ĐÃ HIỆN THỰC (AGT-10): internal/status, internal/cli/status.go, diag.go | Enroll, Credentials, Config |
| FR-18 | Triển khai | service install, uninstall, start, stop, restart cho systemd | AFR-06 | ĐÃ HIỆN THỰC (Linux) | Service và Packaging |
| FR-19 | Triển khai | Gói .deb .rpm, script gói, install.sh có xác minh | (docs/06) | MỘT PHẦN (AGT-6) | Service và Packaging |
| FR-20 | Cấu hình | Cấu hình từ xa ETag, khóa allow_remote_config | AFR-31, AFR-32 | ĐÃ HIỆN THỰC (AGT-10): internal/remotecfg, allow_remote_config: false bỏ mọi khóa trừ cảnh báo min_agent_version | Enroll, Credentials, Config |
| FR-21 | Danh tính | Xoay token định kỳ | AFR-04 | ĐÃ XÂY phía agent (internal/renew), chờ Access Hub endpoint renew (repo collector docs/06 mục 4.7) để chạy thật | Enroll, Credentials, Config |
| FR-22 | Thu thập | Checks service, port, tcp, http, cert | AFR-16 | ĐÃ HIỆN THỰC (AGT-8) | Collectors |
| FR-23 | Thu thập | Kiểm kê | AFR-17 | ĐÃ XÂY (AGT-9) | Collectors, internal/inventory |
| FR-24 | Thu thập, triển khai | Bộ thu, dịch vụ, MSI Windows | AFR-15 | Bộ thu và dịch vụ ĐÃ XÂY (chưa chạy trên Windows thật), MSI CHƯA XÂY (AGT-7) | Collectors, Service và Packaging |
| FR-25 | Cập nhật | Cập nhật tự động có chữ ký | AFR-35 | THIẾT KẾ, CHƯA XÂY (AGT-12) | (chưa có L3) |
4. Non-Functional Requirements
Giá trị lấy từ docs/02-requirements.md (ANFR), mã (hằng số, unit systemd) và L1. Cột Đo được cho biết đã có kiểm thử hay số đo thật chưa. Không có giá trị nào trong bảng là số tự đặt: nếu chưa có nguồn thì ghi "đề xuất".
| STT | Category | Requirement | Target Value | Nguồn, Đo được |
|---|---|---|---|---|
| L2-NFR-01 | Performance | CPU trung bình của agent | Không quá 1% một lõi ở cấu hình chuẩn (70 series, chu kỳ 30 s) | ANFR-01, L1 T1. Đo bằng agent_cpu_percent. Chưa có phép đo dài hạn trên máy thật (tiêu chí thoát giai đoạn 1) |
| L2-NFR-02 | Performance | Bộ nhớ | RSS không quá 50 MB. GOMEMLIMIT mặc định 64 MiB (limits.memory_limit, 16 MiB đến 4 GiB). Trần cứng systemd MemoryMax=96M | ANFR-02, L1 T2, agent.service. Đo bằng agent_rss_bytes |
| L2-NFR-03 | Footprint | Kích thước tệp chạy | Không quá 20 MiB (MAX_BYTES=20971520) cho linux và windows, amd64 và arm64 | ANFR-03, scripts/cross-build.sh. Kiểm bằng dist/sizes.txt |
| L2-NFR-04 | Capacity | Đĩa cho WAL | Mặc định 50 MiB (buffer.max_bytes, 4 MiB đến 1 GiB) và 24 giờ (buffer.max_age, 1 phút đến 7 ngày) | ANFR-04, internal/config/defaults.go, validate.go |
| L2-NFR-05 | Performance | Băng thông mỗi lô | Không quá 10 KB sau nén ở cấu hình chuẩn. Trần cứng 1 MiB nén, 20.000 điểm mỗi request | ANFR-05, internal/transport (MaxCompressedBytes, MaxPointsPerBatch). Mức 10 KB chưa có phép đo trong mã |
| L2-NFR-06 | Performance | Thời gian khởi động | Sẵn sàng thu thập dưới 3 giây | ANFR-06. Chưa có kiểm thử đo |
| L2-NFR-07 | Reliability | Độ bền khi mất điện | Không hỏng WAL, mất tối đa lô đang ghi. Đệm tối thiểu 2 giờ khi mất kết nối | ANFR-07, L1 T5. Kiểm bằng TestWALSurvivesKill9, TestWALTruncatesTornTail, FuzzWALScanRecords. 20 lần mất điện mô phỏng của tiêu chí thoát giai đoạn 1 chưa chạy |
| L2-NFR-08 | Security | Không lắng nghe | 0 cổng mở | ANFR-08. Cấu trúc: chỉ net/http client. Unit giới hạn RestrictAddressFamilies |
| L2-NFR-09 | Reliability | Cách ly lỗi bộ thu | Panic hoặc lỗi ở một bộ thu không dừng agent | ANFR-10, TestEngineIsolatesFailingAndPanickingCollectors |
| L2-NFR-10 | Availability | Tắt êm | Dừng trong 10 giây khi nhận SIGTERM. Unit đặt TimeoutStopSec=30 | ANFR-11. Chưa có kiểm thử đo 10 giây (TestRunStopsOnContextCancel chỉ kiểm dừng khi hủy ngữ cảnh) |
| L2-NFR-11 | Security | Kênh truyền | TLS 1.2 trở lên, xác minh chứng chỉ máy chủ, không theo redirect | L1 T7, TestRedirectsAreNotFollowed, internal/transport |
| L2-NFR-12 | Security | Đặc quyền tối thiểu | Chạy tài khoản accesshub-agent, không capability, NoNewPrivileges, ProtectSystem=strict | ANFR-13, TestPackagedUnitCarriesRequiredHardening |
| L2-NFR-13 | Security | Không lộ bí mật vào log | Token không bao giờ xuất hiện trong log, lỗi, String() | ANFR-14, TestLoggerNeverLeaksSecrets, TestTokenNeverReachesTheLogs, TestNetworkErrorsNeverContainTheToken, TestCredentialsNeverPrintTheToken |
| L2-NFR-14 | Performance | Chu kỳ gửi và phân pha | Mặc định 30 s (10 s đến 300 s). Pha lệch đầu tiên sha256(agent_id) mod interval | defaults.go, TestPhaseOffsetIsStableBoundedAndSpread |
| L2-NFR-15 | Reliability | Lịch backoff | 5 s nhân đôi tới 300 s, full jitter, Retry-After tối đa 1 giờ | internal/backoff, TestScheduleDoublesToCapWithFullJitter |
| L2-NFR-16 | Capacity | Giới hạn series | Cứng 500 series mỗi agent (HardMaxSeries), tự thân dự trữ tối đa 16 | defaults.go, TestSeriesLimitTrimsMainButKeepsSelf |
| L2-NFR-17 | Portability | Phụ thuộc hệ thống | Tệp tĩnh không cần thư viện C (CGO_ENABLED=0). Kernel Linux từ 3.10 và glibc cũ theo docs/02 | ADR 0001. Ma trận distro thật chưa chạy (AGT-6) |
| L2-NFR-18 | Compatibility | Tương thích giao thức | Header X-AH-Proto: 1. Xử lý 426 bằng cách đặt cờ nâng cấp, giữ lô trong WAL và thử lại theo backoff (giao thức ghi "tiếp tục gửi nếu có thể", xem L3 WAL và Sender, OQ-W3). Hỗ trợ N và N-1 theo docs/02 | TestUpgradeRequiredIsFlaggedAndBatchKept. Chỉ có một phiên bản giao thức nên N-1 chưa kiểm được |
5. Technology Stack
| Hạng mục | Lựa chọn | Trạng thái | Lý do, ghi chú |
|---|---|---|---|
| Ngôn ngữ và runtime | Go 1.27.1 (go.mod), tệp tĩnh CGO_ENABLED=0 | SELECTED | ADR 0001. Một tệp, dễ cross-compile, không phụ thuộc thư viện |
| Ngôn ngữ và runtime | Rust | REJECTED | Chưa có ADR riêng. Đội đã chọn Go cho cả Collector để dùng chung .proto và công cụ (đề xuất bổ sung vào ADR 0001) |
| Ngôn ngữ và runtime | Python hoặc Node.js agent | REJECTED | Cần runtime trên máy đích, vượt budget 50 MB RSS (ANFR-02) |
| Mã hóa dây | Protobuf (google.golang.org/protobuf v1.36.12) | SELECTED | Nhỏ, có kiểm tra tương thích (make proto-check) |
| Mã hóa dây | JSON | REJECTED cho số liệu | Chỉ dùng cho /ping và thân lỗi |
| Nén trên dây | gzip | SELECTED (hiện thực) | Giao thức cho phép zstd hoặc gzip. Mã dùng gzip (D-09) |
| Nén trên dây | zstd | REJECTED tạm thời | Cần thư viện ngoài, chưa cần |
| Bộ đệm | WAL tự viết, phân đoạn, CRC32C, deflate | SELECTED | ADR 0002. Không phụ thuộc, kiểm soát phục hồi |
| Bộ đệm | SQLite hoặc BoltDB | REJECTED | Thêm phụ thuộc và kích thước, cần cgo (SQLite) |
| Cấu hình | YAML (go.yaml.in/yaml/v3 v3.0.5) giải mã nghiêm ngặt KnownFields | SELECTED | Khóa lạ là lỗi |
| Nguồn số liệu Linux | Đọc trực tiếp /proc và statfs | SELECTED | Không cần thư viện thứ ba, thử được bằng fixture (os.DirFS) |
| Nguồn số liệu Linux | Nhúng node_exporter hoặc gopsutil | REJECTED | Thêm phụ thuộc và kích thước |
| Nguồn số liệu Windows | PDH với bộ đếm tiếng Anh, lấy hai mẫu | SELECTED (thiết kế) | ADR 0004 (accepted, chờ spike S1). Chưa có mã |
| Dịch vụ Linux | systemd, unit có hardening | SELECTED | internal/svc/accesshub-agent.service |
| Đóng gói | nfpm v2.47.0 cho .deb và .rpm, .tar.gz, install.sh | SELECTED | packaging/nfpm.yaml, scripts/package.sh |
| Đóng gói | MSI (WiX) | SELECTED (thiết kế) | AGT-7 |
| CI | GitLab CI: fmt-vet, lint, govulncheck, test -race, fuzz-smoke, cross-build, proto-drift | SELECTED | .gitlab-ci.yml. Ảnh golang:1.27, golangci-lint v2.14.0, govulncheck v1.8.0 |
| Kiểm thử | go test, fuzz, mockcollector nội bộ, shellcheck cho script gói | SELECTED | internal/mockcollector, packaging/packaging_test.go |
5.1 ADR Log
| Mã | Quyết định | Trạng thái | Tệp |
|---|---|---|---|
| ADR-0001 | Tệp tĩnh, không cgo | Accepted | docs/adr/0001-static-binary-no-cgo.md |
| ADR-0002 | WAL đĩa làm bộ đệm gửi | Accepted. Lệch: WAL đầy xóa lô cũ chỉ ghi log, không cộng vào agent_dropped_samples_total (D-10) | docs/adr/0002-disk-wal-buffer.md |
| ADR-0003 | Kéo cấu hình với ưu tiên cục bộ | Accepted, phần mã CHƯA XÂY (D-01) | docs/adr/0003-config-pull-with-local-precedence.md |
| ADR-0008 | Dịch vụ Windows: tài khoản ảo, khóa ACL thư mục dữ liệu, ánh xạ mã thoát cho SCM | Accepted | docs/adr/0008-windows-service-virtual-account.md |
| ADR-0004 | Windows PDH bộ đếm tiếng Anh | Accepted, chờ spike S1, CHƯA XÂY | docs/adr/0004-windows-pdh-english-counters.md |
| ADR liên quan | ADR 0005: không thực thi mã từ xa, cấu hình từ xa không chứa lệnh hay đường dẫn | Accepted | docs/adr/0005-no-remote-code-execution.md |
Đề xuất thêm ADR mới (chưa tạo, không sửa tệp hiện có): (a) chọn gzip trên dây và deflate trong WAL thay vì zstd, (b) thu tuần tự dưới một timeout chung thay vì song song, (c) hành vi bỏ lô 400 và 422 thay vì thử lại.
6. Integration Architecture
6.1 Thành phần
| Thành phần | Trách nhiệm | Dữ liệu quản lý | Công nghệ | Lưu trữ | Phơi bày ra ngoài |
|---|---|---|---|---|---|
| CMP-1 Runtime Core | Vòng đời tiến trình, vòng lặp chu kỳ, tín hiệu, log có che bí mật, thống kê nội bộ | Trạng thái chạy (halted, cấu hình hiệu lực), bộ đếm stats | Go, log/slog, signal | RAM. Log ra stderr hoặc tệp xoay vòng | Không (SIGHUP, SIGUSR1, SIGTERM cục bộ) |
| CMP-2 Collector Engine | Thu mẫu từ nguồn host, chuẩn hóa, danh sách trắng, giới hạn series | Bộ đếm mẫu trước để tính tốc độ | Go, đọc /proc, statfs | RAM | Không |
| CMP-3 WAL Buffer | Ghi bền lô chờ gửi, phục hồi, dọn theo dung lượng và tuổi | Bản ghi lô đã nén, checkpoint | Go, tệp phân đoạn .seg | Đĩa state_dir/wal (0700, tệp 0600). Dự phòng RAM | Không |
| CMP-4 Sender và Backoff | Đóng lô, chọn lô gửi, phân loại phản hồi, backoff, trạng thái giao | seq, trạng thái giao (ok, backoff, unauthorized, agent_revoked), lịch thử lại | Go | RAM (trạng thái), WAL (lô) | Không |
| CMP-5 Transport Client | Gọi HTTPS tới Collector, TLS, proxy, giới hạn kích thước, ánh xạ lỗi | Không lưu | net/http, protobuf | Không | Gọi ra /agent/v1/* |
| CMP-6 Enroll và Credentials | Nhận token, enroll, lưu và đọc thông tin đăng nhập, machine_id băm, thu hồi tệp token | credentials.json, tệp License (tạm) | Go | Đĩa state_dir/credentials.json (0600) | Không |
| CMP-7 Config Loader | Nạp và kiểm tra cấu hình theo thứ tự ưu tiên | agent.yaml, giá trị hiệu lực | Go, YAML nghiêm ngặt | Đĩa /etc/accesshub-agent/agent.yaml (chỉ đọc với agent) | Không |
| CMP-8 Service và Packaging | Cài, gỡ, điều khiển dịch vụ, tạo tài khoản, thư mục, gói, install.sh | Unit systemd, gói, SHA256SUMS | systemd, nfpm, shell | Đĩa hệ thống, kho gói (chưa có) | Tải gói từ kho qua HTTPS |
6.2 Tích hợp
| Interface | Protocol | Contract | Scope | Sync/Async |
|---|---|---|---|---|
Agent tới Collector: POST /agent/v1/enroll | HTTPS, protobuf | EnrollRequest và EnrollResponse trong agent.proto (accesshub.agent.v1) | Ngoại (qua Internet hoặc mạng khách hàng) | Sync |
Agent tới Collector: POST /agent/v1/metrics (cũng là heartbeat) | HTTPS, protobuf, gzip | MetricsBatch và MetricsAck. Giới hạn 1 MiB nén, 20.000 điểm | Ngoại | Sync theo từng lô, bên gửi lưu đệm nên toàn cục là store-and-forward |
Agent tới Collector: GET /agent/v1/ping | HTTPS, JSON | server_time_ms, proto_min, proto_max | Ngoại | Sync. Mã có Ping nhưng chưa dùng trong vòng chạy |
Agent tới Collector: GET /agent/v1/config | HTTPS, protobuf, If-None-Match | AgentConfig, 304 khi không đổi | Ngoại | Sync. Chỉ dùng để thăm dò khi 401 (mỗi 10 phút). Kéo và áp dụng cấu hình CHƯA XÂY (D-01) |
Agent tới Collector: POST /agent/v1/inventory, POST /agent/v1/credentials/renew, GET /agent/v1/update | HTTPS, protobuf | InventoryFacts, RenewResponse, UpdateManifest | Ngoại | THIẾT KẾ, CHƯA XÂY (D-08) |
Agent tới OS: đọc /proc/*, statfs, /etc/os-release, /etc/machine-id | Tệp cục bộ | Định dạng procfs | Nội bộ máy | Sync |
Quản trị viên tới Agent: CLI, agent.yaml, tín hiệu | Tiến trình cục bộ | Mã thoát 0 đến 6, AH_*, SIGHUP, SIGUSR1 | Nội bộ máy | Sync |
Gói tới hệ thống: dpkg, rpm, systemctl, useradd | Lệnh hệ thống | Script gói packaging/*.sh, biến ACCESSHUB_* | Nội bộ máy | Sync |
install.sh tới kho gói | HTTPS hoặc file:// | SHA256SUMS, SHA256SUMS.sig, gói | Ngoại | Sync. Kho thật chưa có, URL mặc định là chỗ giữ chỗ |
6.3 Khả năng phục hồi (Resilience)
Timeout lấy từ internal/config và internal/transport. Ô "Circuit Breaker" ghi rõ chưa có cơ chế cầu dao riêng: trạng thái backoff và unauthorized của Sender đóng vai trò chặn gọi lặp.
| Hop | Timeout | Retry, Recovery | Backoff, Jitter | Circuit Breaker |
|---|---|---|---|---|
Agent tới Collector metrics | send_timeout mặc định 15 s (1 s đến 1 phút), ResponseHeaderTimeout bằng giá trị này, TLS handshake 10 s | Lô giữ trong WAL, gửi lại ở lượt sau. 400 và 422 bỏ lô. 413 chia đôi rồi gửi mỗi nửa một lần. 401 dừng gửi. 403 dừng vĩnh viễn | 5 s nhân đôi, trần 300 s, full jitter, Retry-After thắng nếu lớn hơn (tối đa 1 giờ), reset sau thành công | Không có cầu dao riêng. Trạng thái unauthorized ngừng gửi và thăm dò config mỗi 10 phút. agent_revoked ngừng hẳn |
Agent tới Collector enroll | send_timeout | Không thử lại tự động. Người vận hành chạy lại. Mã thoát 5 (bị từ chối) hoặc 6 (không kết nối) | Không | Không |
| Agent tới OS (thu mẫu) | collect_timeout mặc định 5 s (1 s đến 30 s, nhỏ hơn interval), một timeout chung cho cả chu kỳ | Lỗi một bộ thu được đếm vào agent_collector_errors, các bộ thu còn lại vẫn chạy | Không | Không |
| Agent tới đĩa (WAL) | Không (I/O đồng bộ, Sync mỗi lần ghi) | Ghi lỗi thì cắt về kích thước cũ. Mở WAL lỗi thì dự phòng bộ đệm RAM | Không | Không |
| Tiến trình tới systemd | TimeoutStopSec=30 | Restart=on-failure, RestartSec=5, không khởi động lại khi thoát mã 2, 3, 4, 5 | Cố định 5 s, StartLimitBurst=10 trong 300 s | Có (giới hạn khởi động lại của systemd) |
install.sh tới kho gói | Mặc định của curl (chưa đặt tường minh) | Không thử lại. Dừng khi checksum hoặc chữ ký sai | Không | Không |
7. Data Architecture
Agent không có cơ sở dữ liệu quan hệ. Dữ liệu bền gồm ba nhóm tệp dưới state_dir và /etc/accesshub-agent. Số liệu chỉ là gauge, không lưu lịch sử ngoài WAL tạm.
7.1 Data Model
| Kho dữ liệu | Vị trí Linux | Nội dung | Chủ sở hữu | Vòng đời |
|---|---|---|---|---|
| Cấu hình cục bộ | /etc/accesshub-agent/agent.yaml | collector_url, interval, giới hạn, bộ lọc, nhãn tĩnh | Quản trị viên máy chủ | Do người vận hành sửa. Gói không ghi đè khi nâng cấp (config|noreplace) |
| Thông tin đăng nhập | state_dir/credentials.json (0600) | agent_id, agent_token, collector_url (tùy chọn), machine_id (băm), enrolled_at | Agent | Tạo khi enroll, xóa khi uninstall --purge hoặc enroll --force ghi đè |
| Tệp License | /etc/accesshub-agent/license.token (0600) | Token dùng một lần | Quản trị viên (tạm) | Ghi đè bằng số 0 rồi xóa sau khi enroll thành công |
| WAL | state_dir/wal/*.seg, checkpoint | Lô MetricsBatch đã nén deflate, có CRC32C | Agent | Xóa khi gửi thành công, khi vượt 50 MiB hoặc 24 giờ |
| Log | stderr (journald) hoặc log.file, xoay ở 10 MB giữ một bản cũ | Sự kiện vận hành đã che bí mật | Agent | Xoay vòng, tối đa khoảng 20 MB |
| Cấu hình từ xa gần nhất | state_dir/remote-config.json (theo docs/04) | Không tồn tại | Không | THIẾT KẾ, CHƯA XÂY (D-01) |
Mô hình khái niệm của một lô gửi (khớp agent.proto):
flowchart TB
classDef owned fill:#2d4a3e,stroke:#5fb37a,color:#fff
classDef sensitive fill:#5a2d2d,stroke:#d96f6f,color:#fff
subgraph AGD["Dữ liệu của Agent"]
B["MetricsBatch: seq, sent_at_ms"]:::owned
S["Series: name, labels"]:::owned
P["Point: ts_ms, value"]:::owned
ST["AgentStats: cpu, rss, wal, drops"]:::owned
CR["credentials.json: agent_id, agent_token"]:::sensitive
end
B -.->|"series"| S
S -.->|"points"| P
B -.->|"stats"| ST
CR -.->|"agent_id"| B7.2 Data Flow Diagram
flowchart TD
classDef entity fill:#3a3320,stroke:#d9b84a,color:#fff
classDef process fill:#1f3a5f,stroke:#4a90d9,color:#fff
classDef datastore fill:#3a2d4a,stroke:#a06fd9,color:#fff
OS(["Hệ điều hành"]):::entity
COL(["Collector"]):::entity
ADM(["Quản trị viên"]):::entity
P1["P1 Thu thập và chuẩn hóa"]:::process
P2["P2 Đóng lô và xếp hàng"]:::process
P3["P3 Gửi và xử lý phản hồi"]:::process
P4["P4 Enroll"]:::process
D1[("Lô số liệu chờ gửi")]:::datastore
D2[("Thông tin đăng nhập")]:::datastore
OS -->|"1. số liệu thô"| P1
P1 -->|"2. mẫu đã chuẩn hóa"| P2
P2 -->|"3. lô đã nén"| D1
COL -->|"4. ack và mã trạng thái"| P3
ADM -->|"5. License"| P4
COL -->|"6. danh tính agent"| P4
P4 -->|"7. token và agent id"| D2Ghi chú về quy ước DFD: thực thể ngoài chỉ có luồng ra, kho dữ liệu chỉ có luồng vào. Luồng đọc kho (P3 đọc lô từ D1, P3 đọc thông tin đăng nhập từ D2) và luồng gửi ra ngoài nằm ở bảng dưới. Số thứ tự luồng: nhóm A (1 đến 3) là số liệu, nhóm B (4) là phản hồi, nhóm C (5 đến 7) là enroll.
Luồng ra ngoài hệ thống (outbound)
| Từ tiến trình | Tới | Dữ liệu | Kênh | Ghi chú |
|---|---|---|---|---|
| P3 | Collector | MetricsBatch (đã gzip) cùng token Bearer | HTTPS POST /agent/v1/metrics | Đọc lô từ D1 và token từ D2 |
| P4 | Collector | EnrollRequest: token, hostname, IP, machine_id băm, OS | HTTPS POST /agent/v1/enroll | Token dùng một lần |
| P3 | Collector | Thăm dò cấu hình khi 401 | HTTPS GET /agent/v1/config | Mỗi 10 phút |
7.3 PII và dữ liệu nhạy cảm
| Trường | Kho | Có PII | Phân loại | Ghi chú |
|---|---|---|---|---|
agent_token | credentials.json | Không | Bí mật (Restricted) | Che khi in, không vào log. Chỉ gửi qua TLS trong header |
| License | Tệp tạm, RAM | Không | Bí mật | Dùng một lần, xóa an toàn |
machine_id | credentials.json, EnrollRequest | Không (định danh thiết bị, đã băm salt) | Nội bộ | sha256("accesshub-agent/machine-id/v1:" + id), không gửi giá trị thô |
hostname, danh sách IP | EnrollRequest | Có thể (định danh hạ tầng, có thể gắn với người dùng cuối nếu đặt tên theo người) | Nội bộ | Chỉ gửi lúc enroll. IP lọc và giới hạn số lượng (hostinfo.usableIPs) |
| Số liệu CPU, RAM, đĩa, mạng | WAL, dây | Không | Nội bộ | Nhãn mount, iface có thể tiết lộ cấu trúc máy nhưng không chứa dữ liệu người dùng |
| Nội dung tệp, tiến trình, người dùng | Không thu | Không áp dụng | Không áp dụng | Agent không thu ngoài danh sách trắng (catalog.go) |
7.4 Data Privacy
Agent giảm thiểu dữ liệu theo thiết kế: danh sách trắng tên chỉ số và nhãn, nhãn company_id, server_id, agent_id bị cấm đặt từ phía agent (tên dành riêng do Collector gán từ danh tính token). Nhãn tĩnh labels bị giới hạn 20 khóa, giá trị tối đa 128 byte. Chưa có yêu cầu pháp lý về dữ liệu cá nhân được nêu trong tài liệu nguồn (Q16 của L1).
7.5 Sở hữu dữ liệu
flowchart TB
classDef owned fill:#2d4a3e,stroke:#5fb37a,color:#fff
classDef sensitive fill:#5a2d2d,stroke:#d96f6f,color:#fff
subgraph AGENT["BC Agent"]
CRED["credentials.json"]:::sensitive
TOK["license.token"]:::sensitive
WAL["WAL lô số liệu"]:::owned
CFG["agent.yaml"]:::owned
end
subgraph COLLECTOR["BC Collector"]
REG["Sổ đăng ký agent"]:::owned
SER["Kho chuỗi thời gian"]:::owned
end
subgraph HUB["BC Access Hub"]
ETK["Bản ghi License"]:::owned
end
CRED -.->|"agent_id"| REG
CRED -.->|"machine_id"| REG
TOK -.->|"license"| ETK
WAL -.->|"agent_id"| SER| Từ | Tới | Trường tham chiếu | Loại tham chiếu |
|---|---|---|---|
credentials.json | Sổ đăng ký agent (Collector) | agent_id | Tham chiếu mềm, Collector xác thực bằng token băm |
credentials.json | Sổ đăng ký agent | machine_id (băm) | Ràng buộc danh tính, sai thì 422 binding_failed khi enroll |
license.token | Bản ghi License (Access Hub) | license | Dùng một lần, trả 409 token_used nếu dùng lại |
| WAL | Kho chuỗi thời gian | agent_id (qua token, không nằm trong lô) | Collector gán company_id, server_id, agent_id từ token |
| Khối nhạy cảm | Bảo vệ |
|---|---|
credentials.json | Quyền 0600, thư mục 0700, ghi nguyên tử, từ chối khi quyền rộng (ErrInsecurePermissions) |
license.token | Quyền 0600 (cảnh báo nếu rộng), ghi đè 0 rồi xóa |
8. Business Flow Diagrams
8.1 Enroll (đường thành công)
sequenceDiagram
participant Adm as Quản trị viên (ext)
participant Ag as Agent
participant Col as Collector (ext)
Adm->>Ag: đưa License qua tệp hoặc stdin
Ag->>Ag: kiểm tra chưa enroll và nạp cấu hình
Ag->>Col: enroll với token và machine id băm
alt token hợp lệ
Col-->>Ag: agent id và agent token
Ag->>Ag: lưu thông tin đăng nhập 0600
Ag->>Ag: ghi đè và xóa tệp token
else bị từ chối hoặc lỗi mạng
Col-->>Ag: mã lỗi
Ag-->>Adm: mã thoát 5 hoặc 6, giữ tệp token
end8.2 Chu kỳ thu và gửi (đường thành công, có gửi bù)
sequenceDiagram
participant Os as Máy chủ (ext)
participant Ag as Agent
participant Wal as WAL
participant Col as Collector (ext)
Ag->>Os: đọc số liệu thô
Ag->>Wal: xếp lô mới xuống đĩa
Ag->>Wal: lấy lô cũ nhất
Ag->>Col: gửi lô
alt thành công
Col-->>Ag: ack kèm server time
Ag->>Wal: xóa lô đã gửi
Ag->>Wal: lấy thêm lô bù trong giới hạn
else lỗi tạm thời
Col-->>Ag: mã 5xx hoặc 429
Ag->>Ag: giữ lô, đặt lịch thử lại
end8.3 Mất kết nối và phục hồi
sequenceDiagram
participant Ag as Agent
participant Wal as WAL
participant Col as Collector (ext)
Ag->>Col: gửi lô
Col--)Ag: không phản hồi hoặc lỗi
Ag->>Wal: giữ lô, tăng khoảng chờ
Note over Ag,Wal: các chu kỳ sau vẫn xếp lô mới vào WAL
Ag->>Col: gửi thử lại theo lịch
Col-->>Ag: ack
Ag->>Wal: gửi bù lô cũ nhất trước8.4 Vòng đời trạng thái agent
Bảy trạng thái ứng với Agent.halted và sender.State trong mã (internal/agent/agent.go, internal/sender/sender.go). Trạng thái không lưu bền, chỉ credentials.json là bền.
stateDiagram-v2
[*] --> BOOT
BOOT --> NOT_ENROLLED: chưa có credentials
NOT_ENROLLED --> BOOT: enroll rồi khởi động lại
BOOT --> HALTED: machine id lệch
BOOT --> OK: credentials hợp lệ
OK --> BACKOFF: lỗi tạm thời
BACKOFF --> OK: gửi thành công
OK --> UNAUTHORIZED: 401
BACKOFF --> UNAUTHORIZED: 401
UNAUTHORIZED --> OK: thăm dò config trả 200
UNAUTHORIZED --> REVOKED: 403
OK --> REVOKED: 403
BACKOFF --> REVOKED: 403
state "Khởi động" as BOOT
state "Chưa enroll (thoát mã 4)" as NOT_ENROLLED
state "Đang gửi (ok)" as OK
state "Chờ thử lại (backoff)" as BACKOFF
state "Mất quyền (unauthorized)" as UNAUTHORIZED
state "Bị thu hồi (agent_revoked)" as REVOKED
state "Dừng do lệch danh tính (identity_mismatch)" as HALTEDGhi chú: HALTED chỉ được kiểm tra một lần lúc khởi động, trước khi tạo Sender. HALTED và REVOKED không có cạnh thoát trong tiến trình: tiến trình chờ tín hiệu dừng, người vận hành xử lý (enroll lại, xóa thông tin đăng nhập) rồi khởi động lại.
9. Security
9.1 Authentication
| Chiều | Cơ chế | Chi tiết | Trạng thái |
|---|---|---|---|
| Agent tới Collector (bình thường) | Bearer token của agent | Authorization: Bearer <agent_token>, token mờ, phía Collector tra cứu và thu hồi, cách lưu do Collector giữ. Cấp lúc enroll, hiển thị một lần | ĐÃ HIỆN THỰC (phía agent) |
| Agent tới Collector (enroll) | License dùng một lần | Trong EnrollRequest.license. Ràng buộc machine_id băm | ĐÃ HIỆN THỰC (phía agent) |
| Collector tới Agent (xác thực máy chủ) | TLS 1.2+ xác minh chứng chỉ, ghim CA tùy chọn (ca_file) | InsecureSkipVerify chỉ bật cục bộ (insecure_skip_verify, AH_INSECURE_SKIP_VERIFY) | ĐÃ HIỆN THỰC |
| Quản trị viên tới Agent | Quyền hệ điều hành (root cho service, tài khoản dịch vụ cho enroll) | service install cần root (ErrNotRoot) | ĐÃ HIỆN THỰC |
| Tăng cường: mTLS phía agent | Chứng chỉ máy khách | AGT-13 | THIẾT KẾ, CHƯA XÂY |
| Tăng cường: xoay token | POST /credentials/renew mỗi 30 ngày, token cũ còn hiệu lực 24 giờ | AGT-10 | ĐÃ XÂY phía agent (credentials.renew_after, mặc định 30 ngày). Chạy thật khi Access Hub có endpoint renew (D-08) |
9.2 Authorization
Agent không có mô hình quyền người dùng. Ma trận dưới đây là ma trận quyền tệp và tiến trình trên máy chủ, đó mới là nơi ranh giới quyền của agent nằm.
| Chủ thể | agent.yaml | credentials.json | license.token | WAL | Unit systemd và CLI service |
|---|---|---|---|---|---|
| root | Đọc, ghi | Đọc, ghi | Đọc, ghi | Đọc, ghi | Cài, gỡ, điều khiển |
Tài khoản accesshub-agent (tiến trình) | Đọc | Đọc, ghi (0600) | Đọc, xóa | Đọc, ghi (0700, 0600) | Không |
| Người dùng khác | Không đọc được (0640 root:accesshub-agent, có thể chứa mật khẩu proxy) | Không (0600, agent từ chối nếu quyền rộng) | Không (0600) | Không | Không |
Phía Collector, quyền của token do Collector quyết định theo mặc định từ chối (deny-by-default): token chỉ ghi số liệu cho đúng company_id và server_id gắn với agent_id, không đọc được gì (L2 Collector).
9.3 Secrets
| Bí mật | Nơi lưu | Bảo vệ | Xoay, thu hồi |
|---|---|---|---|
agent_token | credentials.json 0600, thư mục 0700 | Ghi nguyên tử (temp, chmod, sync, rename, sync thư mục). String() và LogValue() che token | Thu hồi bởi quản trị viên Access Hub (Collector trả 403). Xoay tự động mỗi 30 ngày (internal/renew), token mới ghi nguyên tử trước khi dùng |
| License | Tệp 0600 hoặc stdin hoặc biến môi trường | Ưu tiên tệp và stdin, cờ --token cảnh báo lộ argv. Ghi đè 0 rồi xóa | Dùng một lần, hết hạn phía Access Hub |
| Windows | credentials.json trong thư mục khóa ACL cho SYSTEM, Administrators và NT SERVICE\AccessHubAgent (ADR 0008). DPAPI để sau | Theo docs/04 | ACL ĐÃ XÂY (qua service install), DPAPI CHƯA XÂY |
| Khóa ký gói (GPG hoặc cosign) | Ngoài agent (hệ phát hành) | install.sh chỉ xác minh bằng khóa công khai | Chưa có kho và khóa (Q2, Q3) |
9.4 Application Security
| Hạng mục | Kiểm soát | Bằng chứng |
|---|---|---|
| Không thực thi mã | Không có đường thực thi lệnh, cấu hình không chứa lệnh hay đường dẫn tùy ý | Kiến trúc, ADR 0005 |
| Đầu vào cấu hình | YAML nghiêm ngặt, khóa lạ lỗi, regex RE2 tối đa 200 ký tự, khoảng giá trị | TestLoadErrorsCarryLineNumbers, FuzzLoadNeverPanics |
| Đầu vào thu thập | Danh sách trắng tên, cấm nhãn dành riêng, cắt nhãn 128 byte, bỏ NaN và Inf | TestSanitizeDropsInvalidSamples, TestStaticLabelCannotOverrideReserved |
| Đầu vào phản hồi | Giới hạn thân phản hồi 1 MiB, không theo redirect, cắt thông điệp lỗi 200 ký tự | TestRedirectsAreNotFollowed, internal/transport |
| Tệp WAL hỏng | CRC32C, bỏ bản ghi hỏng, cắt đuôi rách | TestWALSkipsRecordWithBadCRCOnRecovery, FuzzWALScanRecords |
| Chuỗi cung ứng | Phụ thuộc trực tiếp chỉ hai thư viện, govulncheck trong CI, binary tĩnh | go.mod, .gitlab-ci.yml |
| Cài đặt | install.sh xác minh SHA256SUMS và chữ ký (gpg hoặc cosign), không nhận --token trên dòng lệnh, từ chối khi thiếu khóa nếu không có --allow-unsigned | TestInstallRefusesWithoutKeyOrOptOut, TestInstallVerifiesSignature |
Data Masking (UI và Log)
| Dữ liệu | Log | Đầu ra CLI | Ghi chú |
|---|---|---|---|
agent_token, ahat_* | Che | Che (String()) | Bộ lọc che cả thông điệp lẫn thuộc tính, và khóa có tên chứa token, authorization, password, secret |
License ahet_* | Che | Không in | |
Header Authorization: Bearer ... | Che | Không in | Lỗi mạng cũng không chứa token |
| URL collector có userinfo | Bị từ chối khi kiểm cấu hình, có hàm RedactURL cho in log | TestRedactURL | |
| Số liệu, hostname | Không che (không nhạy cảm) | Không che |
Ghi log và kiểm toán: log JSON hoặc văn bản có cấp độ, log.file xoay ở 10 MB giữ một bản cũ. Sự kiện đáng kiểm toán (enroll, bị thu hồi, lệch danh tính, cấu hình nạp lại sai) đều được ghi vào log. Chưa có log kiểm toán riêng ngoài log vận hành. Kiểm toán phía Access Hub và Collector nằm ở L2 của chúng.
Mã hóa
| Dữ liệu | Khi truyền | Khi lưu |
|---|---|---|
| Lô số liệu | TLS 1.2+ | WAL nén deflate, KHÔNG mã hóa (chỉ bảo vệ bằng quyền tệp). Số liệu không nhạy cảm |
agent_token | TLS 1.2+ | Văn bản rõ trong credentials.json 0600 (Linux). DPAPI cho Windows là THIẾT KẾ |
| Gói cài | HTTPS --tlsv1.2 | Không áp dụng. Xác thực bằng chữ ký và SHA256 |
9.5 Mô hình Zero Trust
flowchart LR
classDef bc fill:#1f3a5f,stroke:#4a90d9,color:#fff
classDef owned fill:#2d4a3e,stroke:#5fb37a,color:#fff
classDef entity fill:#3a3320,stroke:#d9b84a,color:#fff
classDef infra fill:#444,stroke:#aaa,color:#fff
ADM(["Quản trị viên Access Hub"]):::entity
SYS(["Quản trị viên máy chủ"]):::entity
subgraph CP["Control Plane"]
HUB["Access Hub cấp License"]:::bc
end
subgraph DP["Data Plane"]
AG["Agent, danh tính workload là agent token"]:::bc
PDP["Collector kiểm token và phân quyền"]:::owned
end
BAS["VPN hoặc Bastion của khách hàng"]:::infra
ADM -->|"1. xác thực quản trị viên"| HUB
HUB -.->|"2. token dùng một lần"| SYS
SYS -->|"3. enroll qua CLI"| AG
AG ==>|"4. TLS cộng Bearer token"| PDP
SYS -->|"5. quản trị từ xa"| BAS
BAS -->|"6. SSH vào máy chủ"| AGBa kiểm tra mỗi yêu cầu:
| Kiểm tra | Cơ chế | Nơi thực thi |
|---|---|---|
| Danh tính người dùng hoặc quản trị viên | Quản trị viên Access Hub xác thực trước khi phát License. Quản trị viên máy chủ cần quyền OS để chạy enroll và service | Access Hub, hệ điều hành |
| Danh tính workload | Agent chứng minh bằng agent_token và machine_id băm. TLS xác thực Collector. mTLS THIẾT KẾ (AGT-13) | Agent, Collector |
| Quyền theo PDP, mặc định từ chối | Collector chỉ chấp nhận token còn hiệu lực, gán company_id và server_id từ token, bỏ qua mọi định danh do agent tự khai (nhãn dành riêng bị cấm) | Collector (L2 Collector) |
Quản trị từ xa (nhánh 5 và 6) đi qua VPN hoặc Bastion do khách hàng vận hành, tách khỏi luồng dữ liệu. Agent không mở cổng quản trị nào.
10. Deployment
10.1 Environments
Tài liệu nguồn chưa mô tả môi trường staging riêng cho agent. Bảng dưới lấy từ những gì có thật trong repo và từ yêu cầu "dev mô phỏng đầy đủ như prod" của chủ hệ thống. Ô không có nguồn ghi "chưa xác định".
| Environment | Purpose | Availability | Infrastructure | Internet Exposure | Data Type | HA/DR | Key Differences |
|---|---|---|---|---|---|---|---|
| Máy phát triển (CI và cục bộ) | Dựng, lint, kiểm thử đơn vị và fuzz, mockcollector | Không cam kết | Runner GitLab (golang:1.27), máy dev | Không phơi bày. CI kéo phụ thuộc | Dữ liệu giả, mockcollector | Không | Không có systemd thật trong CI. Kiểm thử gói dùng ACCESSHUB_PKG_ROOT giả lập |
| Dev prod-like (đang dựng bởi luồng khác) | Chạy agent thật với Collector dev, Redis, VictoriaMetrics | Không cam kết | Chưa xác định trong tài liệu này | Nội bộ | Số liệu host dev | Không | Phải phản ánh đầy đủ prod theo chỉ đạo. Chi tiết ở tài liệu triển khai của dự án |
| Staging | Ma trận distro thật cho AGT-6 (Ubuntu, Debian, Rocky, Amazon Linux) | Chưa xác định | Chưa có | Chưa xác định | Chưa xác định | Chưa xác định | Chưa tồn tại, là điều kiện nghiệm thu AGT-6 |
| Production | Agent chạy trên máy chủ khách hàng | Theo máy chủ đích, dịch vụ tự khởi động lại (Restart=on-failure) | Máy chủ Linux khách hàng (amd64, arm64), Windows là thiết kế | Chỉ egress HTTPS 443 tới Collector | Số liệu host thật | Không HA cho agent. Mất máy là mất nguồn số liệu đó. Bộ đệm WAL chỉ chống mất kết nối | Cấu hình và token khác nhau từng máy |
10.2 Production Deployment Diagram
flowchart TB
classDef bc fill:#1f3a5f,stroke:#4a90d9,color:#fff
classDef datastore fill:#3a2d4a,stroke:#a06fd9,color:#fff
classDef infra fill:#444,stroke:#aaa,color:#fff
DEV(["Nhà phát triển"]):::infra
COLL(["Collector"]):::bc
subgraph CICD["GitLab CI"]
CHK["check: fmt, vet, lint, govulncheck"]:::infra
TST["test: race, fuzz smoke"]:::infra
BLD["build: cross-build và kiểm kích thước"]:::infra
CHK --> TST --> BLD
end
subgraph REL["Phát hành thủ công"]
PKG["package.sh: deb, rpm, tar.gz, SHA256SUMS"]:::infra
REPO[("Kho gói và chữ ký, chưa có")]:::datastore
PKG -.-> REPO
end
subgraph HOST["Máy chủ Linux khách hàng"]
INS["install.sh hoặc dpkg, rpm"]:::infra
subgraph SD["systemd"]
SVC["accesshub-agent.service"]:::bc
end
subgraph DISK["Đĩa cục bộ"]
ETC[("agent.yaml")]:::datastore
STATE[("credentials.json và WAL")]:::datastore
end
INS --> SD
SVC --> STATE
ETC --> SVC
end
DEV --> CICD
BLD -.-> PKG
REPO -.-> INS
SVC ==>|"egress HTTPS 443 allow-list Collector"| COLLChú giải: nét liền là luồng tự động hoặc phụ thuộc trực tiếp, nét đứt là bước thủ công hoặc chưa tự động, nét đậm là egress ra ngoài biên. CI hiện KHÔNG dựng gói, không ký, không đẩy lên kho, không sinh SBOM và không có kênh beta hoặc stable (D-12). Bước "Kho gói và chữ ký" là THIẾT KẾ, CHƯA XÂY (AGT-11).
| Nhóm | Ràng buộc |
|---|---|
| Egress | Chỉ HTTPS 443 tới địa chỉ Collector cấu hình. Proxy qua proxy_url hoặc biến môi trường hệ thống |
| Vị trí ghi | /var/lib/accesshub-agent, /var/log/accesshub-agent (unit đặt ReadWritePaths), phần còn lại chỉ đọc (ProtectSystem=strict) |
| Không ingress | Không mở cổng, unit hạn chế họ địa chỉ AF_INET, AF_INET6, AF_UNIX |
10.3 Deployment Strategy
| Component | Deployment Type | Expected Downtime | Rollback Strategy | Window | Approval Required |
|---|---|---|---|---|---|
Agent trên một máy (gói .deb hoặc .rpm) | Cài đè bằng trình quản lý gói. postinstall gọi try-restart | Vài giây (dừng, khởi động lại, RestartSec=5). Mẫu đã đệm trong WAL, không mất | Cài lại gói phiên bản cũ thủ công. Không có quay lui tự động (AGT-12 THIẾT KẾ, CHƯA XÂY) | Chưa quy định (đề xuất: cửa sổ bảo trì của từng khách hàng) | Chưa quy định (đề xuất: chủ hệ thống phê duyệt trước khi phát hành gói lên kho) |
| Hàng loạt trên nhiều máy | Công cụ cấu hình của khách hàng gọi install.sh với ACCESSHUB_COLLECTOR_URL và token | Như trên, theo từng máy | Như trên | Theo khách hàng | Chưa quy định |
| Cấu hình | Sửa agent.yaml, check-config, SIGHUP | Không (không cần khởi động lại cho khóa đọc lại được) | Khôi phục tệp cũ rồi SIGHUP. Cấu hình sai thì agent giữ cấu hình cũ | Bất kỳ | Không |
| Gỡ cài đặt | accesshub-agent uninstall [--purge] hoặc gỡ gói. Deb purge xóa dữ liệu | Dịch vụ dừng | Cài lại và enroll lại (token mới) | Bất kỳ | Chưa quy định |
| Cập nhật tự động | THIẾT KẾ, CHƯA XÂY (AGT-12) | Không áp dụng | Quay lui sau 5 phút theo thiết kế | Không áp dụng | Không áp dụng |
10.4 Infra & Network Security
| Hạng mục | Giải pháp | Thông số | Phạm vi |
|---|---|---|---|
| Cách ly tiến trình | systemd sandbox | NoNewPrivileges, ProtectSystem=strict, ProtectHome, PrivateTmp, PrivateDevices, ProtectKernel*, ProtectControlGroups, ProtectClock, ProtectHostname, LockPersonality, MemoryDenyWriteExecute, RestrictRealtime, RestrictSUIDSGID, RestrictNamespaces, SystemCallFilter=@system-service, CapabilityBoundingSet rỗng | Mỗi máy Linux (internal/svc/accesshub-agent.service) |
| Trần tài nguyên | Giới hạn cgroup | MemoryMax=96M, CPUQuota=25%, TasksMax=128, LimitNOFILE=1024 | Mỗi máy |
| Tài khoản | Người dùng hệ thống không đăng nhập | accesshub-agent, shell /usr/sbin/nologin, không thư mục home | Mỗi máy |
| Quyền tệp | UMask=0077, thư mục trạng thái 0750 | WAL 0700 và 0600, credentials.json 0600 | Mỗi máy |
| Mạng | Chỉ egress HTTPS | TLS 1.2+, tùy chọn ghim CA, tùy chọn proxy, không theo redirect | Biên máy chủ khách hàng. Quy tắc tường lửa do khách hàng cấu hình (allow-list Collector) |
| Chuỗi cung ứng gói | Checksum và chữ ký | SHA256SUMS, .sig (GPG hoặc cosign) | Kho gói (chưa có) |
10.5 Migration
Không có dữ liệu để di trú từ hệ cũ (chưa có giám sát trước đó, L1 mục 3). Hai điểm cần lưu ý khi nâng cấp: agent.yaml được giữ nguyên (config|noreplace), bản ghi WAL (tiêu đề 24 byte gồm độ dài, CRC32C, id, thời điểm) không mang số phiên bản định dạng, nên mọi thay đổi định dạng bản ghi sau này cần ADR riêng và cơ chế nhận biết bản ghi cũ (D-15).
11. Cost & Capacity
11.1 Capacity / Performance
| Metric | Target | Remarks |
|---|---|---|
| Chu kỳ gửi mỗi agent | 30 s mặc định, 10 s đến 300 s | defaults.go, validate.go. Tải Collector: 10.000 agent ở 30 s khoảng 333 request/s (L1 mục 4) |
| Giới hạn tốc độ phía Collector | 4 request/phút mỗi agent (burst 10) cho metrics, 2 request/phút cho config | docs/10-wire-contract.md. Ở chu kỳ 30 s agent dùng 2 request/phút, còn dư cho gửi bù (catch_up_batches tối đa 10 lô thêm mỗi lượt) |
| Series mỗi agent | Tối đa 500 (cứng), cấu hình chuẩn khoảng 70 | HardMaxSeries, TestSeriesLimitTrimsMainButKeepsSelf |
| Điểm mỗi request | Tối đa 20.000 | MaxPointsPerBatch. Chuẩn hóa mỗi lô một điểm mỗi series |
| Kích thước lô | Tối đa 1 MiB nén, 8 MiB giải nén. Mục tiêu 10 KB sau nén ở cấu hình chuẩn | Mức 10 KB chưa đo (D-16) |
| Đĩa WAL | 50 MiB, 24 giờ | Ước tính từ mục tiêu 10 KB mỗi lô: 50 MiB chứa khoảng 5.000 lô, tức hơn 24 giờ ở chu kỳ 30 s (2.880 lô mỗi 24 giờ), nên giới hạn tuổi chạm trước. Đây là tính toán, chưa đo, cần kiểm chứng |
| RAM | RSS dưới 50 MB, GOMEMLIMIT 64 MiB, trần systemd 96 MiB | ANFR-02 |
| CPU | Dưới 1% một lõi, trần systemd 25% | ANFR-01 |
| Số mount và giao diện | Tối đa 40 mount (MaxMounts) và 20 giao diện (MaxInterfaces) | internal/collector/linux |
11.2 Cost
Tài liệu nguồn không có số liệu chi phí. Bảng dưới liệt kê các mục chi phí đã biết và không điền số.
| Hạng mục | Loại chi phí | Số liệu | Ghi chú |
|---|---|---|---|
| Tài nguyên trên máy khách | CPU, RAM, đĩa, băng thông | Theo budget mục 11.1, không tốn giấy phép | Chi phí của khách hàng, tối thiểu nhờ ràng buộc cứng |
| Hosting kho gói | Hạ tầng | chưa có số liệu | Q2 (người dùng chưa chọn, chỉ có tư vấn) |
| Chứng chỉ ký mã (Windows Authenticode) và khóa ký gói | Giấy phép, vận hành | chưa có số liệu | Q3 (chỉ có tư vấn) |
| Vận hành CI | Runner GitLab | chưa có số liệu | |
| Bản quyền phần mềm | Giấy phép | Không có (Go, protobuf, YAML là mã nguồn mở, giấy phép gói ghi Proprietary) | Cần rà giấy phép phụ thuộc (đề xuất) |
12. Scalability & Reliability
12.1 Scaling
| Thành phần | Chiều mở rộng | Cơ chế | Giới hạn |
|---|---|---|---|
| Agent (mỗi máy) | Không mở rộng, một tiến trình mỗi máy | Giới hạn tài nguyên cứng | 500 series, 40 mount, 20 giao diện |
| Đội agent | Thêm máy | Phân pha lệch sha256(agent_id) mod interval để dàn tải, backoff full jitter tránh đồng loạt khi Collector hồi phục | Do Collector quyết định (L2 Collector) |
| Triển khai hàng loạt | Công cụ của khách hàng gọi install.sh với biến ACCESSHUB_* | Không tự động hóa sẵn | Mẫu first-boot cho image thuộc AGT-11 (chưa xây) |
12.2 Reliability
| Component | Pattern | Failure Handling | Backup/Recovery | Approval |
|---|---|---|---|---|
| Runtime Core | Giám sát bằng systemd | Restart=on-failure, không khởi động lại khi thoát mã 2 (cú pháp), 3 (cấu hình), 4 (chưa enroll), 5 (enroll từ chối) | Khởi động lại đọc WAL và thông tin đăng nhập | Chưa quy định |
| Collector Engine | Cách ly lỗi (bulkhead) | Panic được recover, lỗi bộ thu đếm vào agent_collector_errors, mẫu tự thân vẫn được gửi | Không cần | Chưa quy định |
| WAL Buffer | Store-and-forward, ghi nối tiếp có CRC | Ghi lỗi thì cắt lại. Đĩa không mở được thì dùng RAM (mất khi khởi động lại). Bản ghi hỏng bị bỏ và đếm | Khôi phục khi mở: quét đoạn, cắt đuôi rách, checkpoint nguyên tử | Chưa quy định |
| Sender | At-least-once, trạng thái giao | Xem mục 6.3. Lô có thể gửi lặp sau khởi động lại nếu đã ack nhưng chưa ghi checkpoint (Collector phải idempotent theo seq và mốc thời gian) | Không cần | Chưa quy định |
| Credentials | Ghi nguyên tử | Ghi lỗi giữ tệp cũ, không để tệp tạm | Mất tệp thì enroll lại bằng token mới (Access Hub cấp) | Chưa quy định |
| Service | Cài đặt lặp lại được (idempotent) | service install bỏ qua tài khoản và thư mục đã có, không tự khởi động | Gỡ và cài lại | Chưa quy định |
13. Observability
Tiêu chuẩn tham chiếu: L1 mục 4 (Observability). Cách Collector đánh giá và hiển thị cảnh báo do nhóm Collector giữ, chưa được kiểm ở tài liệu này. Agent tự báo cáo qua hai đường: AgentStats trong mỗi lô và bộ chỉ số agent_* trong catalog. Cảnh báo trên các chỉ số này do Collector đánh giá.
| SLI | Nguồn | SLO đề xuất, chưa xác nhận |
|---|---|---|
| Giao lô thành công | agent_send_failures_total, trạng thái giao | Mất tín hiệu được phát hiện sau không quá 3 chu kỳ cộng 30 s (KPI K2 của L1) |
| Độ trễ đệm | agent_wal_batches, agent_wal_bytes | WAL về 0 lô ở trạng thái ổn định. Ngưỡng cụ thể: đề xuất, chưa xác nhận |
| Mất mẫu | agent_dropped_samples_total (chỉ đếm mẫu bị engine loại và điểm của lô bị bỏ khi gửi, KHÔNG đếm lô bị WAL xóa, D-10) | Bằng 0 ở trạng thái ổn định |
| Chi phí agent | agent_cpu_percent, agent_rss_bytes | Dưới 1% CPU và dưới 50 MB RSS (ANFR-01, ANFR-02) |
| Lệch đồng hồ | agent_clock_skew_seconds | Chưa có ngưỡng nguồn. Collector từ chối điểm cũ hơn 24 giờ hoặc quá 5 phút trong tương lai |
| Sức khỏe bộ thu | agent_collector_errors{collector}, agent_collect_duration_seconds | Bằng 0 lỗi ở trạng thái ổn định. Thời lượng dưới collect_timeout (5 s) |
| Phiên bản và giao thức | agent_info{version,proto,os} | Không có ngưỡng. Thiếu nhãn catalog_version (D-03) |
Chỉ tiêu và ngưỡng cấp thành phần nằm ở mục 13 của từng L3. status và diag (AGT-10) chưa có nên hiện tại chẩn đoán dựa vào log và collect-once.
14. Operational Readiness
| Hạng mục | Giá trị | Ghi chú |
|---|---|---|
| Mức độ bảo mật | Trung bình. Agent chạy trên máy khách hàng, giữ một bí mật (agent token), không nhận lệnh | Đề xuất, chưa được Bảo mật xác nhận |
| System Tier | Đề xuất Cấp độ 3, Business Operational (kế thừa L1 mục 12) | OQ-7 của L1 chưa được xác nhận |
| RPO | Mất mẫu tối đa bằng lô đang ghi (khoảng một interval, mặc định 30 s) khi mất điện. Mất mẫu cũ hơn 24 giờ hoặc vượt 50 MiB khi mất kết nối kéo dài | ANFR-07, buffer |
| RTO | Khởi động lại tự động sau 5 s (RestartSec). Sẵn sàng thu thập dưới 3 s theo thiết kế (chưa đo) | Cộng thời gian phát hiện của systemd |
| Blast radius | Một máy chủ. Lỗi agent không ảnh hưởng máy khác. Bản phát hành lỗi có thể ảnh hưởng mọi máy đã cài, giảm nhẹ bằng phát hành theo đợt (AGT-12 chưa xây) | Rủi ro R-05 |
| DR model | Không sao lưu bắt buộc. Khôi phục = cài gói + enroll lại (token mới) | state_dir không phải nguồn sự thật, Collector giữ danh tính |
| Runbook | docs/09-operations.md (bảng xử lý sự cố), nhưng status và diag mà runbook nhắc tới chưa hiện thực | D-04 |
| Kênh hỗ trợ | Chưa xác định | Cần chủ hệ thống chỉ định (đề xuất) |
15. Testing & Quality Strategy
Tổng cộng 194 hàm kiểm thử và fuzz (đếm ngày 2026-09-30) trên các gói dưới internal/ và packaging/.
| Loại | Phạm vi | Công cụ | Ví dụ |
|---|---|---|---|
| Đơn vị | Mọi package internal/* | go test, CI chạy -race với CGO_ENABLED=1 | TestScheduleDoublesToCapWithFullJitter |
Fixture /proc | Bộ thu Linux | os.DirFS và fixture | TestDiskRealHostFixture, TestRealProcSmoke |
| Fuzz | WAL, cấu hình | go test -fuzz, fuzz-smoke trong CI theo lịch | FuzzWALScanRecords, FuzzLoadNeverPanics |
| Chịu lỗi và mất điện | WAL | Tiến trình con bị kill -9 | TestWALKillChild, TestWALSurvivesKill9 |
| Tích hợp với Collector giả | Sender, transport, agent | internal/mockcollector (kịch bản 401, 403, 413, 429, 5xx, mất kết nối) | TestScriptedStatusesAndAuth, TestRunDeliversBatchesEveryInterval |
| Bảo mật | Rò rỉ token, quyền tệp, redirect | Kiểm thử chuyên biệt | TestLoggerNeverLeaksSecrets, TestWALFilesAreOwnerOnly |
| Đóng gói | Script gói và install.sh | Kiểm thử Go chạy script với thư mục gốc giả, shellcheck | TestPostinstallEnrollsThroughStdinAndStarts, TestShellcheckClean |
| Tĩnh | Định dạng, lint, lỗ hổng, kích thước, drift proto | gofmt, go vet, golangci-lint, govulncheck, cross-build.sh, check-proto-drift.sh | Job CI |
Chưa có (điều kiện nghiệm thu): ma trận distro thật cho AGT-6 (Ubuntu 20.04, 22.04, 24.04, Debian 11, 12, Rocky 8, 9, Amazon Linux 2023), kiểm tra .rpm bằng công cụ rpm, chạy 200 agent giả lập cộng ít nhất 10 agent thật trong 7 ngày, cắt mạng 30 phút, 20 lần mất điện mô phỏng không hỏng WAL (tiêu chí thoát giai đoạn 1, docs/07), đo CPU, RSS và kích thước lô trên máy thật.
16. Risks
16.1 Architecture Risks
Likelihood và Severity là đánh giá của tác giả bản nháp (đề xuất, chưa xác nhận), thang Thấp, Trung bình, Cao.
| Risk ID | Category | Description | Business Impact | Likelihood | Severity | Mitigation | Residual Risk | Owner | Status |
|---|---|---|---|---|---|---|---|---|---|
| R-01 | Delivery | Tài liệu mô tả cấu hình từ xa, kiểm tra (checks), Windows, kiểm kê, xoay token, nhưng mã chưa có (D-01, D-02, D-05, D-08). Người đọc dễ hiểu nhầm là đã có | Kỳ vọng sai về năng lực, mục tiêu L1 mục 2 (mục tiêu 2) chỉ đạt một phần | Cao | Trung bình | Nhãn trạng thái ở mọi tài liệu này. Cập nhật docs/01, docs/04 khi mã đổi | Trung bình đến khi AGT-7 đến AGT-10 xong | chưa chỉ định | Mở |
| R-02 | Security | agent_token là văn bản rõ trong credentials.json, không tự xoay. Kẻ có quyền root trên máy lấy được token | Kẻ tấn công đẩy số liệu giả cho máy đó, không đọc được dữ liệu khác | Thấp | Trung bình | Quyền 0600, unit hạn chế. Xoay token (AGT-10), mTLS (AGT-13), thu hồi ở Access Hub | Thấp sau AGT-10 | chưa chỉ định | Mở |
| R-03 | Supply chain | Gói chưa được ký và chưa có kho. install.sh mặc định trỏ tới URL giữ chỗ. CI không dựng, ký gói (D-12) | Gói giả mạo hoặc không cài được hàng loạt | Trung bình | Cao | install.sh bắt buộc chữ ký hoặc --allow-unsigned tường minh, luôn kiểm checksum. AGT-11 | Cao đến khi có kho và khóa | chưa chỉ định | Mở (Q2, Q3) |
| R-04 | Operability | AGT-6 chưa chạy trên ma trận distro thật, chưa kiểm .rpm bằng rpm, chưa commit (D-13) | Gói lỗi trên một số distro khi phát hành | Trung bình | Trung bình | Chạy ma trận trước khi phát hành | Thấp sau khi chạy ma trận | chưa chỉ định | Mở |
| R-05 | Release | Không có cập nhật tự động, quay lui, phát hành theo đợt (AGT-12) | Bản lỗi đã cài không sửa hàng loạt được, phải sửa từng máy | Trung bình | Trung bình | Phát hành gói thủ công theo đợt nhỏ, giữ gói cũ trong kho | Trung bình | chưa chỉ định | Mở |
| R-06 | Data | Sao chép máy ảo cùng machine-id hoặc đổi machine-id sẽ dừng agent (identity_mismatch), ngược lại hai máy nhân bản dùng chung agent_id nếu chưa đổi machine-id | Mất giám sát máy đó, hoặc số liệu lẫn | Trung bình | Trung bình | Kiểm tra lúc khởi động, runbook nêu cách xử lý (docs/09). Chuẩn hóa image | Thấp | chưa chỉ định | Mở |
| R-07 | Data | WAL hết dung lượng hoặc vượt 24 giờ thì bỏ mẫu cũ nhất. lô bị xóa khỏi WAL chỉ có log cảnh báo và không vào agent_dropped_samples_total (D-10) | Có lỗ hổng số liệu khi mất mạng dài, số đếm thấp hơn thực tế | Trung bình | Thấp | Cho phép tăng buffer.max_bytes và max_age đến 1 GiB và 7 ngày. Sửa cách đếm | Thấp | chưa chỉ định | Mở |
| R-08 | Performance | Các budget (CPU 1%, RSS 50 MB, lô 10 KB, khởi động 3 s) chưa được đo trên máy thật | Có thể vượt khi nhiều mount hoặc giao diện | Trung bình | Thấp | Trần cứng bằng số series, số mount, giới hạn systemd. Đo trong giai đoạn 1 | Thấp | chưa chỉ định | Mở |
| R-09 | Compatibility | Chỉ có một phiên bản giao thức nên N-1 chưa kiểm chứng được. 426 chỉ cờ hóa, không nâng cấp | Agent cũ ngừng được hỗ trợ mà không có đường nâng cấp | Thấp | Trung bình | AGT-12, kiểm thử tương thích khi có proto v2 | Thấp | chưa chỉ định | Mở |
| R-10 | Delivery | Lô 400 và 422 bị bỏ, lô không chia được và quá lớn bị bỏ. Một lỗi hợp đồng có thể làm rơi hàng loạt mẫu mà chỉ có log | Mất số liệu âm thầm | Thấp | Trung bình | Đếm vào dropped, log rõ lý do, kiểm thử hợp đồng bằng make proto-check | Thấp | chưa chỉ định | Mở |
16.2 Open Issues and Tech Debt
D-01 đến D-13 là sai lệch giữa tài liệu thiết kế và mã (mã thắng). D-14 đến D-16 là nợ kỹ thuật và tài liệu.
| Debt ID | System | Description | Reason | Impact | Priority | Remediation | Effort | Owner | Resolution Date | Status |
|---|---|---|---|---|---|---|---|---|---|---|
| D-01 | Agent, cấu hình | Cấu hình từ xa không có. OnConfigETag không được gán, GetConfig chỉ dùng cho thăm dò 401, không ghi remote-config.json, allow_remote_config không dùng. Thứ tự ưu tiên thật: cờ > env > tệp > mặc định | Thuộc AGT-10 | docs/01, docs/04, ADR 0003, giao thức 2.4 mô tả lớp từ xa chưa có | Cao | AGT-10: kéo, kiểm tra, áp dụng, lưu đĩa | đề xuất, chưa ước | chưa chỉ định | chưa có | Mở |
| D-02 | Agent, thu thập | checks (service, port, tcp, http, cert) được phân tích và kiểm tra nhưng không có bộ thu. checks_allow_link_local không dùng. Các chỉ số service_up, port_up, tcp_connect_*, http_*, cert_days_left không bao giờ được phát | AGT-8 chưa làm | Cấu hình checks không có tác dụng, âm thầm | Cao | AGT-8, hoặc cảnh báo khi checks không rỗng | đề xuất, chưa ước | chưa chỉ định | chưa có | Mở |
| D-03 | Agent, catalog | disk_read_bytes_per_sec, disk_write_bytes_per_sec, disk_io_util_percent, open_fds_percent có trong danh sách trắng nhưng không bộ thu nào phát. agent_info thiếu catalog_version | Chưa làm | Thiếu số liệu I/O đĩa và fd | Trung bình | Thêm bộ thu hoặc bỏ khỏi catalog | đề xuất, chưa ước | chưa chỉ định | chưa có | Mở |
| D-04 | Agent, CLI | status và diag là stub (stub("status","AGT-10")) | AGT-10 | Runbook docs/09 nhắc tới lệnh chưa có | Trung bình | AGT-10 | đề xuất, chưa ước | chưa chỉ định | chưa có | Mở |
| D-05 | Agent, Windows | Không có mã Windows (bộ thu, dịch vụ, MSI, DPAPI). Thông báo CLI từng ghi "AGT-8" trong khi roadmap ghi Windows là AGT-7 | AGT-7 | Nhầm mã công việc | Thấp | Đã sửa thông báo thành AGT-7 | Nhỏ | đã làm | chưa có | Đã đóng |
| D-06 | Agent, thu thập | Engine.Collect chạy các bộ thu tuần tự dưới MỘT timeout chung cho cả chu kỳ. docs/01 viết song song và timeout 5 s mỗi bộ thu | Đơn giản hóa | Một bộ thu chậm ăn hết thời gian của bộ thu sau | Thấp | Cập nhật tài liệu hoặc đổi mã | Nhỏ | chưa chỉ định | chưa có | Mở |
| D-07 | Agent, cấu trúc | Không có Scheduler, Normalizer, Config manager, Inventory, Updater, internal/app như docs/01. Tốc độ tính trong bộ thu, chuẩn hóa và giới hạn trong engine, vòng thời gian trong agent.go | Thiết kế thu gọn | Tài liệu docs/01 lệch cấu trúc | Thấp | Cập nhật docs/01 theo tài liệu này | Nhỏ | chưa chỉ định | chưa có | Mở |
| D-08 | Agent, transport | Agent đã gọi POST /credentials/renew (AGT-10, collector trả 503 đến khi Access Hub có endpoint), chưa có GET /update, dù agent.proto đã khai báo thông điệp (POST /inventory đã có từ AGT-9) | AGT-10, AGT-12 | Không xoay token, không cập nhật | Trung bình | Theo AGT tương ứng | đề xuất, chưa ước | chưa chỉ định | chưa có | Mở |
| D-09 | Agent, transport | Nén trên dây là gzip, docs/03 nói zstd hoặc gzip. WAL dùng deflate | Chọn phương án không cần thư viện | Nhất quán với giao thức (cho phép gzip) | Thấp | Ghi ADR | Nhỏ | chưa chỉ định | chưa có | Mở |
| D-10 | Agent, WAL, thống kê | Lô bị WAL xóa do đầy hoặc quá tuổi (buffer.Stats.Dropped, đếm theo lô) chỉ sinh log buffer full, oldest batches dropped (internal/sender/sender.go), không cộng vào Stats.DroppedSamples. Chỉ số agent_dropped_samples_total chỉ gồm mẫu bị engine loại (sai tên, nhãn, NaN, trùng, vượt series) và điểm của lô bị bỏ vì 400, 422, không chia được. docs/03 mô tả chỉ số là "mẫu bị bỏ do WAL đầy" | Chưa nối số đếm WAL vào thống kê | Mất số liệu do mất mạng dài không hiện trên chỉ số và không tới Collector qua AgentStats | Trung bình | Cộng số điểm ước tính của lô bị xóa hoặc thêm chỉ số riêng, và sửa mô tả docs/03 | Nhỏ | chưa chỉ định | chưa có | Mở |
| D-11 | Agent, enroll | collector_url do enroll trả về được lưu vào credentials.json nhưng không dùng lúc chạy. collector_url cục bộ luôn thắng | Thiết kế cho GĐ 3 | Không ảnh hưởng, chỉ dữ liệu chết | Thấp | Giữ đến AGT-10 rồi quyết định | Nhỏ | chưa chỉ định | chưa có | Mở |
| D-12 | Agent, CI và phát hành | CI không dựng gói, không ký, không SBOM, không kênh beta hoặc stable, không đẩy kho. install.sh mặc định https://downloads.example.com/agent và email maintainer trong nfpm là chỗ giữ chỗ | AGT-11 | Không thể phát hành thật | Cao | AGT-11, chốt Q2, Q3 | đề xuất, chưa ước | chưa chỉ định | chưa có | Mở |
| D-13 | Agent, đóng gói | AGT-6 chưa commit (Makefile, docs/04, docs/06, docs/07, cli.go bị sửa, internal/svc, packaging/, scripts/package.sh chưa theo dõi). Ma trận distro thật và kiểm tra .rpm bằng rpm chưa làm | Đang dở | Không thể coi AGT-6 xong | Cao | Commit sau khi chủ hệ thống duyệt, chạy ma trận | đề xuất, chưa ước | chưa chỉ định | chưa có | Mở |
| D-14 | Tài liệu | Runtime Core (internal/agent, logx, stats) chưa có L3 riêng | Phạm vi bản nháp | Một phần hành vi (chu kỳ, dừng êm, log) chỉ ở L2 và L3 lân cận | Thấp | Viết L3 Runtime Core khi cần (đề xuất) | Vừa | chưa chỉ định | chưa có | Mở |
| D-15 | Agent, WAL | Bản ghi WAL không có số phiên bản định dạng. Remove ngoài thứ tự chỉ đúng trong phiên chạy (đánh dấu trong RAM), sau khởi động lại có thể gửi lặp | Đơn giản hóa | Rủi ro nâng cấp định dạng, gửi lặp (Collector phải idempotent) | Thấp | Thêm phiên bản định dạng khi cần đổi | Nhỏ | chưa chỉ định | chưa có | Mở |
| D-16 | Kiểm chứng | Chưa đo CPU, RSS, kích thước lô, thời gian khởi động và dừng trên máy thật. Chưa có kiểm thử đo dừng trong 10 giây | Chưa đến giai đoạn nghiệm thu | NFR chưa được chứng minh | Trung bình | Chạy phép đo trong tiêu chí thoát giai đoạn 1 | Vừa | chưa chỉ định | chưa có | Mở |
Câu hỏi mở của L2 này:
| # | Câu hỏi | Hành vi tạm thời | Owner |
|---|---|---|---|
| OQ-A1 | Ai là Owner và người phê duyệt của L2 này? | Ghi "chưa chỉ định", trạng thái BẢN NHÁP | chưa chỉ định |
| OQ-A2 | Xác nhận System Tier (đề xuất 3) với EA | Dùng đề xuất của L1 | EA |
| OQ-A3 | Có giữ gzip trên dây hay chuyển zstd (D-09)? | Giữ gzip | chưa chỉ định |
| OQ-A4 | Có nhận checks cấu hình cục bộ khi chưa có bộ thu (D-02): cảnh báo hay lỗi? | Đọc và bỏ qua không cảnh báo | chưa chỉ định |
| OQ-A5 | Lịch AGT-7 (Windows) và spike S1 (ADR 0004) | Không có Windows | chưa chỉ định |
| OQ-A6 | Q2 (kho gói), Q3 (chứng chỉ ký) | Chủ dự án xác nhận 2026-10-01: sẽ quyết và mua sau vì còn đang phát triển. Chỉ có tư vấn | Người dùng |
Appendix A. Glossary
| Thuật ngữ | Nghĩa |
|---|---|
| Agent | Chương trình accesshub-agent chạy trên máy chủ được giám sát |
| Collector | Dịch vụ nhận số liệu, xác thực agent, lưu và đánh giá cảnh báo |
| Access Hub | Nền tảng điều khiển, phát hành License, hiển thị trạng thái |
| License | Token dùng một lần cấp bởi Access Hub để đăng ký agent |
| Agent token | Token dài hạn của agent sau enroll, dùng trong header Bearer |
| WAL | Write-ahead log, bộ đệm ghi trước trên đĩa của lô chờ gửi |
| Heartbeat | Lô rỗng gửi đúng lịch để Collector biết agent còn sống |
| Gauge | Chỉ số dạng giá trị tức thời |
| Catch-up | Gửi bù lô cũ trong WAL, có giới hạn số lô mỗi lượt |
| Phase offset | Độ lệch pha gửi đầu tiên theo hash agent_id để dàn tải |
| PDP | Policy Decision Point, điểm ra quyết định phân quyền |
| RE2 | Bộ máy regex của Go, không quay lui |
| STD-DIAG | Chuẩn vẽ sơ đồ kiến trúc của tổ chức |
Appendix B. References
| Tài liệu | Vị trí |
|---|---|
| L1 HLD | L1-HLD-agent.md |
| Hợp đồng Agent - Collector | docs/10-wire-contract.md, internal/wire/accesshub/agent/v1/agent.proto.ref |
| Tài liệu Agent | docs/00 đến docs/10 trong repo Agent |
| ADR Agent | docs/adr/0001 đến 0004 |
| Mã nguồn | internal/**, cmd/accesshub-agent, packaging/**, scripts/**, .gitlab-ci.yml, Makefile |
| Khung tài liệu | Tài liệu L2 - Thiết kế chi tiết kiến trúc (SAD), HD - Luồng Tài Liệu Thiết Kế Kiến Trúc, Danh Mục - Tiêu Chuẩn Diagram v1.1 |
Quyết định kiến trúc
| Số | Quyết định | Trạng thái | Ngày |
|---|---|---|---|
| 0001 | Binary tĩnh, không dùng CGO | Chấp nhận | 30/09/2026 |
| 0002 | Bộ đệm WAL trên đĩa tự viết, giới hạn dung lượng | Chấp nhận | 30/09/2026 |
| 0003 | Cấu hình kéo từ collector, khóa an toàn ưu tiên cục bộ | Chấp nhận | 30/09/2026 |
| 0004 | Windows dùng PDH với tên bộ đếm tiếng AnhThay một phần 0007 | Cần xác nhận | 30/09/2026 |
| 0005 | Không thực thi mã từ xa | Chấp nhận | 30/09/2026 |
| 0006 | Chọn chỉ số bằng glob include, exclude trên danh mục định nghĩa trong mã | Chấp nhận | 30/09/2026 |
| 0007 | Bộ thu Windows dùng API trực tiếp trước, PDH để sauThay một phần 0004 | Chấp nhận | 02/10/2026 |
| 0008 | Dịch vụ Windows chạy bằng tài khoản ảo và khóa ACL thư mục dữ liệu | Chấp nhận | 02/10/2026 |