Access Hub Agent
Đồng bộ từ mã nguồn lúc 15:42, 03/10/2026
Skip to content

L3 - Monitoring Platform - Agent - Service và Packaging (Dịch vụ systemd, gói cài đặt, bộ cài) ​

Trạng thái
Bản nháp
Phiên bản
0.1, ngày 30/09/2026

Ghi chú: khi tài liệu và mã khác nhau, mã thắng

Đã làm nghĩa là có mã và kiểm thử trong repo. Chỉ thiết kế nghĩa là có trong tài liệu nhưng chưa có mã. Chỗ lệch được ghi ở mục nợ kỹ thuật.

Thông tin tài liệu đầy đủ
TrườngGiá trị
Tên trangL3 - Monitoring Platform - Agent - Service và Packaging
Trạng tháiBẢN NHÁP (tài liệu chưa sẵn sàng trình thẩm định)
Phiên bảnv0.1, 2026-09-30: bản nháp đầu tiên, dựng từ mã tại commit a23f929 cộng các tệp AGT-6 chưa commit (internal/svc, internal/cli/service.go, packaging/, scripts/package.sh, các mục package và snapshot trong Makefile, docs/06-packaging-install.md). AGT-6 chưa commit và chưa chạy trên ma trận distro thật, xem L2 D-13 và R-04. Hai kiểm tra thủ công một lần (systemd-analyze verify, dựng gói bằng nfpm) được nêu ở mục 14
Tên dự ánMonitoring Platform (Access Hub Monitoring)
Bên thẩm định / Phê duyệtchưa chỉ định. Chưa ai sign-off
Tài liệu tầng trên (Parent)L2 - Monitoring Platform - Agent - SAD, thành phần CMP-8 Service và Packaging (mục 2.3). FR-18, FR-19, FR-24 (phần Linux), L2-NFR-02, 03, 08, 10, 12, 13, 17, rủi ro R-03, R-04, nợ D-05, D-12, D-13. Truy vết tiếp lên L1: L1 HLD mục 2 (Mục tiêu 6), mục 3 (K4, T3, T4, T8)
Tài liệu anh emL3 Collectors, L3 WAL và Sender, L3 Enroll, Credentials và Config
Mục lục0 Governance, 1 Phạm vi, 2 Yêu cầu, 3 Kiến trúc, 4 Domain model, 5 Hợp đồng API, 6 Dữ liệu vật lý, 7 Thuật toán, 8 Xử lý lỗi, 9 Suy thoái, 10 Đồng thời, 11 Bảo mật, 12 Cấu hình, 13 Telemetry, 14 Kiểm thử, 15 Trình tự xây dựng, Phụ lục A, B, C

Quy ước nhãn trạng thái (giống L2): ĐÃ HIỆN THỰC (đã xác minh trong mã), THIẾT KẾ, CHƯA XÂY (chỉ có trong tài liệu thiết kế), MỘT PHẦN, ĐỀ XUẤT. Khi mã và tài liệu khác nhau, mã thắng và sai lệch được nêu trong tài liệu này và gom về L2 mục 16.2. Mọi con số chưa có trong mã hoặc giao thức được gắn nhãn "đề xuất". Câu nào ghi "suy luận từ mã" nghĩa là rút ra từ việc đọc mã, chưa chạy thật trên máy đích.


0. Front Matter & Approvals ​

Governance metadata

TrườngGiá trị
ComponentCMP-8 Service và Packaging: internal/svc (Manager, RenderUnit, unit nhúng accesshub-agent.service), internal/cli/service.go (lệnh service và uninstall), packaging/ (nfpm.yaml, agent.yaml mẫu, bốn script gói, install.sh, packaging_test.go), scripts/package.sh, scripts/cross-build.sh và các mục build, cross, package, snapshot, checksums của Makefile
Truy vết L2L2-SAD-agent.md mục 2.3, 3 (FR-18, FR-19, FR-24), 4 (L2-NFR-02, 03, 08, 10, 12, 13, 17), 10 (triển khai), 16 (R-03, R-04, D-05, D-12, D-13)
Phân loại rủi roĐề xuất, chưa xác nhận: Tier 2. Lý do: thành phần chạy bằng root lúc cài, sinh ra tài khoản hệ thống và thư mục, và là cửa vào chuỗi cung ứng (R-03). Sau khi cài, tiến trình agent chạy không đặc quyền nên mức rủi ro vận hành thấp hơn
Data classificationBí mật khi chuyển License qua biến môi trường, tệp token hoặc ống (postinstall.sh, install.sh). Nội bộ cho agent.yaml (có thể chứa proxy_url kèm mật khẩu, tệp 0640 root:accesshub-agent), unit, gói. Công khai cho nội dung gói và SHA256SUMS
Blast radiusMột máy chủ cho mọi lỗi cài đặt và gỡ. Riêng khâu phát hành (package.sh, kho gói, khóa ký) ảnh hưởng mọi máy cài bằng gói đó (R-03). Lỗi nặng nhất: gói bị đánh tráo chạy bằng root trong postinstall. Lỗi purge xóa credentials.json buộc enroll lại một máy

Sign-off gate

Vai tròTênTrách nhiệm duyệtTrạng tháiNgày
Tech lead thành phầnchưa chỉ địnhĐúng đắn của internal/svc, script gói, install.sh, package.shChưa duyệtchưa có
SA hệ thống Agentchưa chỉ địnhNhất quán với L2, L3 Enroll, docs/06Chưa duyệtchưa có
Bảo mậtchưa chỉ địnhHardening unit, quyền tệp, chuỗi xác minh gói, xử lý token trong postinstallChưa duyệtchưa có
Vận hành và phát hànhchưa chỉ địnhMa trận distro, kho gói, khóa ký, kênh phát hành (Q2, Q3)Chưa duyệtchưa có

1. Component Scope & Non-Goals ​

Vai trò: thành phần này là lớp đưa agent lên máy chủ Linux và giữ nó chạy ổn định dưới systemd. Nó gồm bốn việc: (1) một unit systemd đã siết quyền, là nguồn duy nhất cho cả gói lẫn lệnh service install (mẫu một nguồn sự thật nhúng vào tệp chạy), (2) bộ quản lý svc.Manager tạo tài khoản, thư mục, unit và điều khiển dịch vụ cho kiểu cài thủ công từ tệp nhị phân, (3) gói .deb và .rpm do nfpm dựng cùng bốn script gói, tự enroll khi có biến môi trường (mẫu cài không tương tác, không bao giờ làm hỏng gói vì enroll), (4) bộ cài install.sh tải, xác minh chữ ký và checksum rồi gọi trình quản lý gói (mẫu xác minh rồi mới tin). Cùng với package.sh dựng bộ phát hành. Thành phần không có tiến trình nền của riêng nó và không mở cổng nào.

Sơ đồ ngữ cảnh

mermaid
flowchart LR
  classDef bc fill:#1f3a5f,stroke:#4a90d9,color:#fff
  classDef owned fill:#2d4a3e,stroke:#5fb37a,color:#fff
  classDef datastore fill:#3a2d4a,stroke:#a06fd9,color:#fff
  classDef sensitive fill:#5a2d2d,stroke:#d96f6f,color:#fff
  classDef infra fill:#444,stroke:#aaa,color:#fff

  ADM(["Quản trị viên hoặc Ansible"]):::infra
  REPO(["Nơi phát hành gói: HTTPS hoặc file"]):::infra
  SD(["systemd và trình quản lý gói"]):::infra
  FS[("Unit, agent.yaml, state, log")]:::datastore

  subgraph BC["Service và Packaging"]
    INS["install.sh"]:::owned
    PKG["Gói deb rpm và script gói"]:::owned
    SVC["svc.Manager và lệnh service"]:::owned
    UNIT["Unit systemd đã siết"]:::sensitive
  end

  ENR["Enroll CLI: enroll --token-stdin"]:::bc
  RT["Runtime: run"]:::bc

  ADM -->|"chạy"| INS
  INS -->|"tải và xác minh"| REPO
  INS -->|"cài gói"| SD
  SD -->|"giải nén và chạy script"| PKG
  PKG -->|"enroll trong postinstall"| ENR
  PKG -->|"enable và start"| SD
  ADM -->|"service install"| SVC
  SVC -->|"ghi unit, tạo thư mục"| FS
  UNIT -->|"ExecStart run"| RT

Mô tả quan hệ

ChiềuBênNội dung
VàoQuản trị viênLệnh install.sh với cờ (--version, --base-url, --pubkey, --allow-unsigned, --proxy, --no-start, --dry-run), biến môi trường (ACCESSHUB_COLLECTOR_URL, ACCESSHUB_LICENSE, ACCESSHUB_LICENSE_FILE, ACCESSHUB_PROXY_URL, ACCESSHUB_NO_START, ACCESSHUB_DOWNLOAD_BASE, ACCESSHUB_PUBKEY_FILE), lệnh accesshub-agent service <install|uninstall|start|stop|restart> và accesshub-agent uninstall [--purge]
VàoTrình quản lý góiĐối số script (deb: configure, upgrade, remove, purge, deconfigure. rpm: số 0 hoặc 1)
VàoNơi phát hànhlatest, SHA256SUMS, SHA256SUMS.sig, gói .deb hoặc .rpm (HTTPS hoặc file://). Kho thật chưa có (L2 Q2)
VàoNgười phát hànhMã nguồn, nfpm, VERSION, COMMIT, DATE, SIGN_HOOK cho package.sh
RaHệ tệp/usr/bin/accesshub-agent, unit (/lib/systemd/system cho deb, /usr/lib/systemd/system cho rpm, hoặc /etc/systemd/system do service install), /etc/accesshub-agent/agent.yaml, /var/lib/accesshub-agent, /var/log/accesshub-agent, tài khoản accesshub-agent
Rasystemddaemon-reload, enable, enable --now, try-restart, disable --now, start, stop, restart
RaCLI enrollaccesshub-agent enroll --token-stdin chạy bằng tài khoản dịch vụ, token đi qua ống
RaNgười phát hànhBộ phát hành: .deb, .rpm, .tar.gz cho amd64 và arm64, install.sh, SHA256SUMS, tùy chọn SHA256SUMS.sig

Trong phạm vi (bao phủ)

Trong phạm viGhi chú
Unit accesshub-agent.service với hardening, trần tài nguyên, chính sách khởi động lại theo mã thoátinternal/svc/accesshub-agent.service. ĐÃ HIỆN THỰC
Nhúng unit vào tệp chạy và viết lại ExecStart theo đường dẫn tệp chạyinternal/svc/unit.go (PackagedUnit, RenderUnit). ĐÃ HIỆN THỰC
Tạo tài khoản, thư mục, ghi unit, daemon-reload, enable; gỡ, tùy chọn purge; start, stop, restartinternal/svc/systemd.go (Manager). ĐÃ HIỆN THỰC (Linux)
Lệnh service install|uninstall|start|stop|restart và uninstallinternal/cli/service.go. ĐÃ HIỆN THỰC (Linux). Chưa commit (D-13)
Cấu hình gói nfpm: tệp, chế độ, thư mục state, config|noreplace, scriptpackaging/nfpm.yaml. ĐÃ HIỆN THỰC. Kiểm thủ công bằng bản dựng deb và rpm một lần
Bốn script gói: preinstall, postinstall, preremove, postremovepackaging/scripts/. ĐÃ HIỆN THỰC. Kiểm thử bằng shim, không cài gói thật
Cấu hình mẫu agent.yamlinternal/svc/agent.yaml (nhúng vào binary để service install ghi được, cũng là nguồn của gói). ĐÃ HIỆN THỰC
Bộ cài install.sh (Debian và RHEL)packaging/install.sh. ĐÃ HIỆN THỰC. Đường su và đường rpm của install.sh chưa có kiểm thử
Dựng bộ phát hành: hai kiến trúc, deb, rpm, tar.gz, SHA256SUMS, móc kýscripts/package.sh, make package, make snapshot. ĐÃ HIỆN THỰC
Dựng chéo bốn mục tiêu và kiểm trần 20 MiBscripts/cross-build.sh, make cross, job CI cross-build. ĐÃ HIỆN THỰC
Bản ghi docs/06-packaging-install.mdTài liệu vận hành gói. Đã đối chiếu với mã
Ma trận distro thật, kiểm .rpm bằng rpm, commit AGT-6ĐỀ XUẤT (R-04, D-13)
Job CI dựng, ký gói, đẩy kho, SBOM, kênh beta và stableTHIẾT KẾ, CHƯA XÂY (AGT-11, D-12)
Dịch vụ Windows, MSI (WiX), install.ps1, AuthenticodeTHIẾT KẾ, CHƯA XÂY (AGT-7, L2 D-05). Lệnh service trên Windows trả thông báo và mã 1
Cập nhật tự động có chữ kýTHIẾT KẾ, CHƯA XÂY (AGT-12, FR-25), không thuộc tài liệu này

Ngoài phạm vi

Không thuộc BCThuộc về
Nội dung lệnh enroll, thứ tự nhận token, ghi credentials.json, nạp agent.yamlL3 Enroll, Credentials và Config
Vòng chu kỳ, WAL, gửi, tín hiệu SIGHUPL3 WAL và Sender, Runtime Core (L2 D-14)
Đọc /proc, danh sách trắng chỉ sốL3 Collectors
Kho gói (apt, yum), khóa ký, chọn nơi lưu, kênh phát hànhHệ phát hành bên ngoài agent (L2 Q2, Q3, AGT-11)
Phát hành và ràng buộc LicenseAccess Hub và Collector
Công cụ quản lý cấu hình hàng loạt (Ansible, Puppet)Quản trị viên. Thành phần chỉ cam kết giao diện môi trường và mã thoát ổn định

2. Detailed Requirements & Acceptance Criteria ​

Yêu cầu chức năng (FR-P)

#Trách nhiệmGiải thíchHiện thực ở
FR-P01Unit một nguồnMột tệp unit duy nhất được nhúng vào tệp chạy (go:embed) và được nfpm đóng gói, không có bản sao thứ haiinternal/svc/unit.go, nfpm.yaml (ĐÃ HIỆN THỰC)
FR-P02Hardening và trần tài nguyênChạy bằng accesshub-agent, không capability, ProtectSystem=strict, bộ lọc syscall, chỉ AF_INET, AF_INET6, AF_UNIX, MemoryMax=96M, CPUQuota=25%, TasksMax=128, LimitNOFILE=1024accesshub-agent.service (ĐÃ HIỆN THỰC)
FR-P03Chính sách khởi động lạiRestart=on-failure cách 5 giây, dừng hẳn với mã 2, 3, 4, 5, giới hạn 10 lần trong 300 giâyaccesshub-agent.service (ĐÃ HIỆN THỰC)
FR-P04Cài dịch vụ thủ côngservice install kiểm root, đường dẫn tuyệt đối, tạo tài khoản và thư mục, ghi unit viết lại ExecStart, daemon-reload, tùy chọn enable, không bao giờ startsvc.Manager.Install, cli.serviceInstall (ĐÃ HIỆN THỰC)
FR-P05Gỡ dịch vụ thủ côngservice uninstall và uninstall: disable --now, xóa unit, daemon-reload. Với --purge xóa thêm state, log, cấu hình và tài khoảnsvc.Manager.Uninstall (ĐÃ HIỆN THỰC)
FR-P06Điều khiển dịch vụservice start|stop|restart qua systemctl, yêu cầu root, từ chối hành động lạsvc.Manager.Control (ĐÃ HIỆN THỰC)
FR-P07Gói deb và rpmMột cấu hình nfpm cho hai định dạng và hai kiến trúc, đặt unit đúng thư mục theo định dạng, agent.yaml là config|noreplace, thư mục state 0750packaging/nfpm.yaml, scripts/package.sh (ĐÃ HIỆN THỰC)
FR-P08Script gói idempotentpreinstall tạo tài khoản, postinstall chuẩn bị thư mục và (nếu có biến môi trường) cấu hình, enroll, khởi động, preremove chỉ dừng khi gỡ thật, postremove chỉ xóa dữ liệu khi deb purgepackaging/scripts/*.sh (ĐÃ HIỆN THỰC)
FR-P09Cài không tương tácVới ACCESSHUB_COLLECTOR_URL và token, postinstall ghi collector_url, enroll bằng tài khoản dịch vụ qua ống và enable --now. Enroll lỗi không làm hỏng góipostinstall.sh (ĐÃ HIỆN THỰC)
FR-P10Kiểm giá trị trước khi ghi YAMLURL phải bắt đầu https:// và chỉ gồm ký tự trong danh sách trắng, nếu không thì bỏ qua enrollvalid_value, set_key (ĐÃ HIỆN THỰC)
FR-P11Bộ cài xác minhinstall.sh bắt buộc khóa công khai hoặc --allow-unsigned, luôn kiểm checksum, chọn tên gói từ SHA256SUMS đã xác minhpackaging/install.sh (ĐÃ HIỆN THỰC)
FR-P12Bộ phát hànhpackage.sh dựng deb, rpm, tar.gz cho amd64 và arm64, install.sh, SHA256SUMS, và gọi SIGN_HOOK nếu cóscripts/package.sh (ĐÃ HIỆN THỰC)
FR-P13Phiên bản góiTag vX.Y.Z thành X.Y.Z, mọi thứ khác thành 0.0.0-dev.<7 ký tự commit>, ký tự lạ thành dấu chấmscripts/package.sh (ĐÃ HIỆN THỰC)
FR-P14Kiểm trần kích thướcDựng chéo bốn mục tiêu và thất bại nếu vượt MAX_BYTES (mặc định 20 MiB)scripts/cross-build.sh, job cross-build (ĐÃ HIỆN THỰC)
FR-P15Ma trận distro và kiểm rpmChạy gói trên các distro mục tiêu và kiểm .rpm bằng rpmĐỀ XUẤT (R-04)
FR-P16Job CI đóng gói và kýCI dựng, ký, đẩy kho, SBOMTHIẾT KẾ, CHƯA XÂY (AGT-11, D-12)
FR-P17Dịch vụ Windows và MSICài, gỡ, điều khiển trên Windows, MSI, install.ps1THIẾT KẾ, CHƯA XÂY (AGT-7, D-05)

Yêu cầu phi chức năng (NFR-P)

NFRTargetParent L2-NFR (Kiểu)Satisfied-by
NFR-P01Tiến trình agent chạy bằng tài khoản accesshub-agent, CapabilityBoundingSet rỗng, NoNewPrivileges=yes, ProtectSystem=strictL2-NFR-12 (Security)Unit, TestPackagedUnitCarriesRequiredHardening
NFR-P02Không lắng nghe: RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX, không có tham số mở cổngL2-NFR-08 (Security)Unit
NFR-P03Trần tài nguyên cứng MemoryMax=96M, CPUQuota=25%, TasksMax=128, LimitNOFILE=1024. Ngân sách vận hành (50 MB RSS, 1% một lõi) thấp hơn nhiềuL2-NFR-02, L2-NFR-01 (Performance)Unit. Xem OQ-P4 về chênh lệch với limits.memory_limit
NFR-P04Dừng êm: TimeoutStopSec=30, gửi SIGTERM, runtime dừng trong 10 giâyL2-NFR-10 (Availability)Unit. Không có kiểm thử đo 10 giây
NFR-P05Tệp chạy không quá 20 MiB cho bốn mục tiêuL2-NFR-03 (Footprint)cross-build.sh, job cross-build
NFR-P06Tệp tĩnh CGO_ENABLED=0, gói không phụ thuộc thư viện ngoàiL2-NFR-17 (Portability)package.sh. Ma trận distro chưa chạy (OQ-P12)
NFR-P07Chuỗi cung ứng: không bao giờ bỏ qua kiểm checksum, không chữ ký thì dừng trừ khi có --allow-unsigned tường minhR-03 của L2 (Security)install.sh, TestInstallRefusesWithoutKeyOrOptOut, TestInstallAllowUnsignedStillChecksums, TestInstallVerifiesSignature
NFR-P08Token cài đặt không đi qua argv: bộ cài từ chối --token, postinstall đưa token vào ống stdinL2-NFR-13 (Security)install.sh, postinstall.sh, TestPostinstallEnrollsThroughStdinAndStarts, TestInstallRejectsUnsafeInput
NFR-P09Idempotent: cài lại hoặc nâng cấp giữ credentials.json và agent.yaml, chạy lại preinstall và postinstall an toànL2 mục 10.3 (Reliability)config|noreplace, TestPostinstallKeepsExistingCredentials, TestPostinstallReplacesExistingCollectorURLOnce
NFR-P10Lỗi enroll không làm hỏng gói: postinstall luôn thoát 0 ở nhánh enroll lỗiADR-E09 của L3 Enroll (Reliability)TestPostinstallEnrollFailureDoesNotFailPackageOrStart
NFR-P11Không khởi động lại vô hạn với lỗi không thể tự khỏi: mã 2, 3, 4, 5 dừng hẳn, còn lại tối đa 10 lần trong 300 giâyL2 mục 12.2 (Reliability)Unit (RestartPreventExitStatus, StartLimitBurst). Không có kiểm thử hành vi thật
NFR-P12Một nguồn unit: nội dung unit trong gói và trong service install giống hệt, chỉ khác ExecStartL2 mục 2.2 (Maintainability)go:embed, TestRenderUnitRewritesOnlyTheBinary, TestNfpmSourcesExist

Tiêu chí nghiệm thu (AC-P)

ACGiven / When / ThenTruy vết → Test ID
AC-P01Given unit đóng gói, When đọc nội dung, Then chứa User=accesshub-agent, các chỉ thị hardening, trần tài nguyên, RestartPreventExitStatus=2 3 4 5, WantedBy=multi-user.target và không có dấu gạch ngang dàiFR-P02, FR-P03, NFR-P01 → TestPackagedUnitCarriesRequiredHardening
AC-P02Given đường dẫn tệp chạy khác mặc định, When RenderUnit, Then chỉ dòng ExecStart đổi, ExecReload giữ nguyên, đường dẫn mặc định cho ra unit không đổiFR-P01, FR-P04 → TestRenderUnitRewritesOnlyTheBinary
AC-P03Given root và tệp chạy hợp lệ, When Install, Then tài khoản, thư mục, unit được tạo và daemon-reload chạyFR-P04 → TestInstallCreatesAccountDirsUnitAndReloads
AC-P04Given tài khoản đã có và không truyền --enable, When Install, Then không tạo lại tài khoản và không enableFR-P04 → TestInstallKeepsExistingAccountAndSkipsEnableByDefault
AC-P05Given không phải root hoặc đường dẫn tương đối, When Install, Then từ chốiFR-P04 → TestInstallRequiresRootAndAbsoluteBinary, TestServiceInstallHonorsBinaryFlagAndRejectsRelative
AC-P06Given không có useradd, When Install, Then báo lỗi rõ cách tự tạo tài khoảnFR-P04 → TestInstallFailsClearlyWithoutUseradd
AC-P07Given dịch vụ đã cài, When Uninstall không purge, Then dữ liệu còn, và với --purge thì state, log, cấu hình và tài khoản bị xóaFR-P05 → TestUninstallKeepsDataUnlessPurge
AC-P08Given dịch vụ chưa nạp, When Uninstall, Then chỉ cảnh báo, không lỗiFR-P05 → TestUninstallToleratesServiceThatIsNotLoaded
AC-P09Given hành động lạ hoặc không phải root, When Control, Then từ chốiFR-P06 → TestControlValidatesActionAndRoot, TestServiceNeedsRootAndAKnownAction
AC-P10Given lệnh service install --enable không có --binary, When chạy, Then unit dùng tệp chạy hiện tại, systemctl enable được gọi (không start) và hướng dẫn enroll được inFR-P04 → TestServiceInstallWritesUnitForThisExecutable
AC-P11Given hệ điều hành không phải Linux, When service hoặc uninstall, Then thông báo và mã 1FR-P17 → TestServiceIsLinuxOnlyForNow
AC-P12Given service start|stop|restart và uninstall, When chạy qua CLI, Then gọi đúng systemctlFR-P05, FR-P06 → TestServiceControlAndUninstall
AC-P13Given bốn script và install.sh, When kiểm cú pháp, Then phân tích được và có quyền thực thi, và sạch shellcheck khi có công cụFR-P08 → TestScriptsParseAndAreExecutable, TestShellcheckClean
AC-P14Given nfpm.yaml, When kiểm, Then mọi src và script được tham chiếu tồn tại và agent.yaml mẫu hợp lệ khi có collector_urlFR-P07 → TestNfpmSourcesExist, TestSampleConfigIsValidWithCollectorOverride
AC-P15Given không có biến môi trường, When postinstall, Then chỉ chuẩn bị thư mục, không enroll, không enable --nowFR-P08, FR-P09 → TestPostinstallWithoutEnvOnlyPreparesDirectories
AC-P16Given URL và token hợp lệ, When postinstall, Then token đi qua stdin, enroll bằng tài khoản dịch vụ và dịch vụ được enable --nowFR-P09, NFR-P08 → TestPostinstallEnrollsThroughStdinAndStarts
AC-P17Given collector_url đã có, When postinstall chạy lại, Then khóa được thay một lần, không nhân đôiFR-P10, NFR-P09 → TestPostinstallReplacesExistingCollectorURLOnce
AC-P18Given tệp token, When enroll thành công, Then tệp bị xóaFR-P09 → TestPostinstallTokenFileIsRemovedAfterEnroll
AC-P19Given đã có credentials.json, When postinstall, Then giữ nguyên, không enroll lạiNFR-P09 → TestPostinstallKeepsExistingCredentials
AC-P20Given enroll lỗi, When postinstall, Then thoát 0, không khởi động, gói vẫn được càiNFR-P10 → TestPostinstallEnrollFailureDoesNotFailPackageOrStart
AC-P21Given ACCESSHUB_NO_START=1, When postinstall, Then chỉ enable, không startFR-P09 → TestPostinstallNoStartOnlyEnables
AC-P22Given URL hoặc proxy chứa ký tự ngoài danh sách trắng hoặc không phải https, When postinstall, Then bỏ qua enroll và không sửa agent.yamlFR-P10 → TestPostinstallRejectsUnsafeValues
AC-P23Given chỉ có URL hoặc chỉ có token, When postinstall, Then không enrollFR-P09 → TestPostinstallNeedsBothURLAndToken
AC-P24Given preremove và postremove với đối số nâng cấp, gỡ thường và purge, When chạy, Then chỉ dừng khi gỡ thật và chỉ xóa dữ liệu khi purgeFR-P08 → TestPreremoveOnlyStopsOnRealRemoval, TestPostremoveKeepsDataUnlessPurge
AC-P25Given không có khóa công khai và không có --allow-unsigned, When install.sh, Then dừng. Với --allow-unsigned vẫn từ chối gói sai checksumFR-P11, NFR-P07 → TestInstallRefusesWithoutKeyOrOptOut, TestInstallAllowUnsignedStillChecksums
AC-P26Given khóa công khai và chữ ký, When install.sh, Then chữ ký đúng mới cài, sai thì từ chốiFR-P11 → TestInstallVerifiesSignature
AC-P27Given đầu vào xấu (token trên dòng lệnh, URL, phiên bản, tên gói), When install.sh, Then từ chốiFR-P11, NFR-P08 → TestInstallRejectsUnsafeInput

Các AC cho FR-P12 đến FR-P14 (package.sh, cross-build.sh) không có kiểm thử tự động trong kho, chỉ có kiểm tra thủ công một lần (mục 14). Các AC cho FR-P15 đến FR-P17 chưa có vì chức năng chưa xây.

Kịch bản chất lượng (QAS-P)

Mã kịch bản / NFRNguồn & Kích thíchMôi trườngPhản hồiThước đo
QAS-P01 / NFR-P09, NFR-P10Quản trị viên chạy install.sh hàng loạt với URL và token lỗi trên một máyCài đặt thông thường, mạng tới Collector hỏngGói vẫn cài xong, dịch vụ không khởi động, postinstall in cách enroll lạiMã thoát của trình quản lý gói là 0 (TestPostinstallEnrollFailureDoesNotFailPackageOrStart). Tỉ lệ thành công trên đội máy chưa có số liệu
QAS-P02 / NFR-P07Kẻ tấn công thay gói trên kho bằng gói khácKho gói bị chiếminstall.sh dừng trước khi gọi trình quản lý góiChữ ký SHA256SUMS sai hoặc checksum lệch đều dẫn tới thoát 1 (kiểm thử shim, không phải kho thật)
QAS-P03 / NFR-P01Mã agent bị khai thácDịch vụ đang chạyTiến trình bị giam: không capability, chỉ ghi được state và log, không tạo được socket ngoài ba họ địa chỉKiểm bằng systemd-analyze verify (chỉ cú pháp). Chưa có kiểm thử xâm nhập hay systemd-analyze security (đề xuất)
QAS-P04 / NFR-P11Cấu hình sai sau khi sửa tayDịch vụ chạyrun thoát mã 3 và systemd không khởi động lạiDừng hẳn sau lần thoát đầu nhờ RestartPreventExitStatus. Lỗi mã 1 thì thử lại tối đa 10 lần trong 300 giây
QAS-P05 / NFR-P09Nâng cấp gói khi dịch vụ đang chạyNâng cấp thườngGiữ cấu hình và danh tính, khởi động lại dịch vụ bằng tệp chạy mớitry-restart chạy trong postinstall. Thời gian gián đoạn chưa có số liệu
QAS-P06 / NFR-P09Gỡ gói bằng remove rồi cài lạiGỡ thườngKhông cần enroll lạiTestPostremoveKeepsDataUnlessPurge. Với rpm không có purge (OQ-P8)

3. Kiến trúc ứng dụng ​

3.1. Kiến trúc runtime ​

Thành phần này không có tiến trình thường trực. Nó là một tập lệnh chạy ngắn, theo ba đường vào: (1) trình quản lý gói chạy bốn script, (2) quản trị viên chạy install.sh (chạy một lần rồi thoát, gọi trình quản lý gói), (3) quản trị viên chạy accesshub-agent service ... trực tiếp. Sau khi cài xong, thứ còn lại trên máy là unit systemd, và systemd là bên giữ tiến trình run chạy.

mermaid
flowchart LR
  classDef bc fill:#1f3a5f,stroke:#4a90d9,color:#fff
  classDef owned fill:#2d4a3e,stroke:#5fb37a,color:#fff
  classDef datastore fill:#3a2d4a,stroke:#a06fd9,color:#fff
  classDef sensitive fill:#5a2d2d,stroke:#d96f6f,color:#fff
  classDef infra fill:#444,stroke:#aaa,color:#fff

  INS["install.sh"]:::owned
  PM(["dpkg apt rpm dnf yum"]):::infra
  SCR["Script gói: pre và post"]:::owned
  MGR["svc.Manager"]:::owned
  UNIT["Unit đã siết"]:::sensitive
  SD(["systemd"]):::infra
  FS[("agent.yaml, credentials, state")]:::datastore
  ENR["enroll --token-stdin"]:::bc

  INS -->|"cài gói"| PM
  PM -->|"chạy script"| SCR
  SCR -->|"ghi khóa, tạo thư mục"| FS
  SCR -->|"runuser enroll"| ENR
  ENR -->|"credentials 0600"| FS
  SCR -->|"enable và try-restart"| SD
  MGR -->|"ghi unit, systemctl"| SD
  MGR -->|"tạo thư mục"| FS
  SD -->|"nạp"| UNIT

Chú giải: nét liền là lời gọi đồng bộ trong cùng một tiến trình shell hoặc Go. Toàn bộ tác động phụ của svc.Manager đi qua các trường hàm (Run, LookPath, Lookup, Chown, Euid) nên thay được trong kiểm thử. Script gói đọc ACCESSHUB_PKG_ROOT và ACCESSHUB_BIN (chỉ để kiểm thử) để chạy không cần quyền root.

Bảng connector

ConnectorTừTớiCơ chếĐồng bộGhi chú
CN-P1install.shNơi phát hànhcurl -fsSL --proto '=https,file' --tlsv1.2, tùy chọn -x proxyĐồng bộTải latest, SHA256SUMS, SHA256SUMS.sig, gói. Lỗi tải thì die
CN-P2install.shTrình quản lý góiapt-get install -y, dpkg -i, dnf install -y, yum install -y, rpm -UĐồng bộChọn theo công cụ có sẵn. Biến môi trường được export để script gói đọc
CN-P3Trình quản lý góiScript góiĐối số vị trí (deb: từ khóa, rpm: số)Đồng bộpreremove.sh và postremove.sh phân biệt nâng cấp, gỡ, purge
CN-P4postinstall.shaccesshub-agent enrollrunuser -u accesshub-agent -- hoặc su -s /bin/sh -c, token qua ốngĐồng bộEnroll chạy bằng tài khoản dịch vụ để credentials.json thuộc về nó. Xem L3 Enroll CN-E2
CN-P5Script gói, svc.Managersystemdsystemctl daemon-reload, enable, enable --now, try-restart, disable --now, start, stop, restartĐồng bộLỗi systemctl trong script bị nuốt (|| true hoặc cảnh báo). Trong svc.Manager lỗi được trả ra (trừ disable --now và daemon-reload khi gỡ, chỉ cảnh báo)
CN-P6svc.ManagerHệ tệp và tài khoảnos.MkdirAll, Chmod, Chown, os.WriteFile, useradd, userdelĐồng bộuseradd qua Run để thay được trong kiểm thử
CN-P7Lệnh servicesvc.ManagernewServiceManager(env)Đồng bộBiến hàm để kiểm thử thay bằng bản giả (serviceOS, executablePath cũng vậy)
CN-P8package.shgo build, nfpmDựng tĩnh cho hai kiến trúc, nfpm package --packager deb|rpmĐồng bộnfpm không mở rộng biến môi trường trong contents.src nên package.sh dùng sed thay ${AGENT_BINARY}

3.2. Kiến trúc module ​

mermaid
flowchart LR
  classDef bc fill:#1f3a5f,stroke:#4a90d9,color:#fff
  classDef owned fill:#2d4a3e,stroke:#5fb37a,color:#fff
  classDef datastore fill:#3a2d4a,stroke:#a06fd9,color:#fff
  classDef sensitive fill:#5a2d2d,stroke:#d96f6f,color:#fff
  classDef infra fill:#444,stroke:#aaa,color:#fff

  CLI["cli/service.go"]:::owned
  SVC["svc/systemd.go"]:::owned
  UNI["svc/unit.go"]:::owned
  UF["accesshub-agent.service"]:::sensitive
  NFP["packaging/nfpm.yaml"]:::owned
  SH["packaging/scripts và install.sh"]:::owned
  PK["scripts/package.sh"]:::owned

  CLI -->|"Install, Uninstall, Control"| SVC
  SVC -->|"RenderUnit"| UNI
  UNI -->|"go:embed"| UF
  NFP -->|"src unit"| UF
  NFP -->|"scripts"| SH
  PK -->|"sed và nfpm package"| NFP

3.2.1. Cấu trúc: gói svc và lệnh service ​

Thành phầnTệpVai tròGhi chú
ServiceName, PackagedBinary, Accountsvc/unit.go, svc/systemd.goHằng số: accesshub-agent, /usr/bin/accesshub-agent, accesshub-agentĐường dẫn tệp chạy và tài khoản cũng được gõ cứng trong unit, nfpm và script
packagedUnit, PackagedUnit()svc/unit.goNội dung unit nhúng bằng go:embedCùng tệp được nfpm đóng gói, một nguồn
RenderUnit(bin)svc/unit.goThay ExecStart=/usr/bin/accesshub-agent bằng ExecStart=<bin> Không thoát ký tự đặc biệt trong bin (OQ-P6). Bin rỗng hoặc mặc định thì trả nguyên bản
Managersvc/systemd.goThư mục (UnitDir, ConfigDir, StateDir, LogDir), hàm tiêm (Euid, Run, LookPath, Lookup, Chown, Log)NewManager đặt /etc/systemd/system, /etc/accesshub-agent, /var/lib/accesshub-agent, /var/log/accesshub-agent
Install(InstallOptions)svc/systemd.goKiểm root, đường dẫn tuyệt đối, ensureAccount, ensureDirs, ensureConfig (ghi agent.yaml mẫu 0640 root:accesshub-agent chỉ khi chưa có, kèm collector_url nếu có CollectorURL), ghi unit 0644, daemon-reload, tùy chọn enableKhông start. Không bao giờ sửa agent.yaml đã có (OQ-P3). CollectorURL sai (không https:// hoặc ký tự lạ) trả ErrCollectorURL trước mọi tác dụng phụ
Uninstall(purge)svc/systemd.godisable --now (lỗi chỉ cảnh báo), xóa unit, daemon-reload, nếu purge xóa ba thư mục rồi userdelChỉ xóa unit ở UnitDir (OQ-P13)
Control(action)svc/systemd.gostart, stop, restart qua systemctlTừ chối hành động khác và không phải root
ensureAccount, ensureDirssvc/systemd.gouseradd --system --user-group --no-create-home --home-dir <state> --shell /usr/sbin/nologin, thư mục state và log 0750 thuộc tài khoản, thư mục cấu hình 0755Nếu không có useradd trả lỗi nói cách tự tạo (không thử adduser, khác preinstall.sh)
ErrNotRootsvc/systemd.goLỗi khi không phải rootCLI in lỗi và thoát mã 1
serviceCmd, serviceInstall, serviceUninstall, uninstallCmd, reportServiceErrorcli/service.goLệnh service, uninstall, cờ --binary, --enable, --collector, --purgeMọi lỗi dịch vụ thoát mã 1, sai cách dùng mã 2. Windows: thông báo nêu AGT-7 (đã sửa, OQ-P9)

3.2.2. Cấu trúc: gói cài và phát hành ​

Thành phầnTệpVai tròGhi chú
Cấu hình nfpmpackaging/nfpm.yamlTên, kiến trúc, phiên bản (${NFPM_ARCH}, ${PKG_VERSION}), nội dung, scriptUnit vào /lib/systemd/system cho deb và /usr/lib/systemd/system cho rpm. agent.yaml kiểu config|noreplace 0640 root:accesshub-agent. Thư mục state 0750 thuộc accesshub-agent. README vào /usr/share/doc. Không có thư mục log (OQ-P7)
preinstall.shpackaging/scripts/Tạo tài khoản bằng useradd, hoặc adduser, hoặc thoát 1Chạy lại an toàn (thoát sớm nếu tài khoản có)
postinstall.shpackaging/scripts/Tạo thư mục, daemon-reload, try-restart, rồi (nếu có biến) ghi khóa, enroll, enableChi tiết ở 7.1 và 7.4
preremove.shpackaging/scripts/disable --now chỉ với remove, deconfigure, 0Nâng cấp không dừng dịch vụ
postremove.shpackaging/scripts/daemon-reload, và với purge xóa ba thư mục và userdelrpm không có purge (OQ-P8)
agent.yaml mẫuinternal/svc/agent.yamlMọi khóa được chú thích, collector_url bị commentGói không ghi đè khi nâng cấp
install.shpackaging/install.shTải, xác minh, chọn định dạng, càiChi tiết ở 5.1 và 7.4
package.shscripts/package.shDựng bộ phát hànhYêu cầu nfpm v2.47.0 (thông báo lỗi của script ghi phiên bản này)
cross-build.shscripts/cross-build.shDựng bốn mục tiêu, kiểm trần kích thướcTrần MAX_BYTES mặc định 20971520
packaging_test.gopackaging/Kiểm thử script bằng shim PATH và thư mục gốc giảXem mục 14
Mục MakefileMakefilebuild, cross, package, snapshot, checksumssnapshot dựng vào dist/snapshot với phiên bản 0.0.0-snapshot.<sha>

4. Domain model ​

Có hai nhóm khái niệm độc lập: dịch vụ trên máy (unit, tài khoản, bố cục thư mục) và phát hành (bộ phát hành, bản kê SHA256SUMS, yêu cầu cài đặt). Mỗi nhóm một sơ đồ.

mermaid
classDiagram
  namespace Vung_Dich_Vu {
    class ServiceUnit {
      <<Aggregate Root>>
      +Name accesshub_agent_service
      +ExecStart binary_run
      +RestartPolicy on_failure_5s
      +NoRestartExit 2_3_4_5
      +Hardening strict_no_caps
      +Ceilings mem96M_cpu25_tasks128_nofile1024
    }
    class ServiceAccount {
      <<Entity>>
      +Name accesshub_agent
      +Shell nologin
      +Home state_dir
    }
    class InstallLayout {
      <<Value Object>>
      +ConfigDir etc_accesshub_agent_0755
      +StateDir var_lib_0750
      +LogDir var_log_0750
    }
    class InstallOptions {
      <<Value Object>>
      +Binary absolute_path
      +Enable bool
    }
    class Manager {
      <<Domain Service>>
      +Install
      +Uninstall
      +Control
    }
  }
  Manager --> ServiceUnit : ghi
  Manager --> ServiceAccount : tạo nếu thiếu
  Manager --> InstallLayout : tạo
  InstallOptions ..> Manager : tham số
  ServiceUnit ..> ServiceAccount : chạy bằng
mermaid
classDiagram
  namespace Vung_Phat_Hanh {
    class ReleaseSet {
      <<Aggregate Root>>
      +Packages deb_rpm_targz_x_2_arch
      +Installer install_sh
      +Manifest SHA256SUMS
      +Signature optional
    }
    class PackageVersion {
      <<Value Object>>
      +Value digit_first
      +Source git_describe_or_dev
    }
    class InstallRequest {
      <<Value Object>>
      +CollectorURL https_only
      +License secret
      +ProxyURL optional
      +NoStart bool
    }
    class VerificationChain {
      <<Policy>>
      +Key pubkey_or_allow_unsigned
      +Checksum required
    }
  }
  ReleaseSet *-- PackageVersion : mang
  VerificationChain ..> ReleaseSet : kiểm
  InstallRequest ..> ReleaseSet : cài từ
Thực thểLoạiMô tảNơi định nghĩa
ServiceUnitAggregate RootTệp unit systemd duy nhất, nhúng vào tệp chạy và góiinternal/svc/accesshub-agent.service
ServiceAccountEntityTài khoản hệ thống accesshub-agent, shell nologin, home là thư mục statesvc.Account, preinstall.sh
InstallLayoutValue ObjectBa thư mục: cấu hình 0755, state 0750, log 0750svc.Manager.ensureDirs, postinstall.sh, nfpm.yaml
InstallOptionsValue ObjectBinary tuyệt đối và Enablesvc.InstallOptions
ManagerDomain ServiceCài, gỡ, điều khiển, mọi tác động phụ qua trường hàmsvc.Manager
ReleaseSetAggregate RootKết quả một lần package.shscripts/package.sh
PackageVersionValue ObjectChuỗi phiên bản bắt đầu bằng chữ sốscripts/package.sh
InstallRequestValue ObjectBộ biến môi trường của người càiinstall.sh, postinstall.sh
VerificationChainPolicyKhóa công khai hoặc --allow-unsigned tường minh, cộng checksum bắt buộcinstall.sh

Bất biến (INV-P)

MãBất biếnThi hành bởi
INV-P1Nội dung unit chỉ có một nguồn. RenderUnit chỉ sửa dòng ExecStart, không chạm ExecReloadgo:embed, nfpm.yaml, TestRenderUnitRewritesOnlyTheBinary
INV-P2service install không bao giờ khởi động dịch vụ, vì chưa enroll thì run không chạy đượcsvc.Manager.Install (chỉ enable khi có --enable), TestInstallKeepsExistingAccountAndSkipsEnableByDefault
INV-P3License không xuất hiện trên dòng lệnh: install.sh từ chối --token, postinstall đưa token qua ốnginstall.sh, postinstall.sh, TestInstallRejectsUnsafeInput, TestPostinstallEnrollsThroughStdinAndStarts
INV-P4Giá trị ghi vào agent.yaml đi qua danh sách trắng ký tự và collector_url phải là https://valid_value, TestPostinstallRejectsUnsafeValues
INV-P5Enroll trong postinstall chạy bằng tài khoản dịch vụ, để credentials.json thuộc tài khoản mà dịch vụ chạyrun_as (runuser hoặc su), TestPostinstallEnrollsThroughStdinAndStarts
INV-P6Gỡ thường và nâng cấp giữ credentials.json và agent.yaml. Chỉ deb purge (hoặc uninstall --purge) mới xóaconfig|noreplace, postremove.sh, preremove.sh, TestPostremoveKeepsDataUnlessPurge, TestPreremoveOnlyStopsOnRealRemoval, TestUninstallKeepsDataUnlessPurge
INV-P7Không cài khi chưa xác minh: phải có khóa công khai hoặc --allow-unsigned, và checksum luôn được kiểminstall.sh, TestInstallRefusesWithoutKeyOrOptOut, TestInstallAllowUnsignedStillChecksums
INV-P8Tên gói được chọn từ SHA256SUMS đã xác minh và không được chứa / hay ký tự lạinstall.sh (PKG_NAME), TestInstallRejectsUnsafeInput
INV-P9Lỗi enroll không làm hỏng gói: nhánh enroll lỗi thoát 0postinstall.sh, TestPostinstallEnrollFailureDoesNotFailPackageOrStart
INV-P10Phiên bản gói luôn bắt đầu bằng chữ số và không chứa ký tự ngoài A-Za-z0-9.+~-scripts/package.sh. Không có kiểm thử tự động
INV-P11Mã thoát 2, 3, 4, 5 không được systemd thử lạiUnit (RestartPreventExitStatus), TestPackagedUnitCarriesRequiredHardening (kiểm chuỗi, không kiểm hành vi)
INV-P12Lệnh cần quyền hệ thống (Install, Uninstall, Control) từ chối khi không phải rootsvc.Manager.needRoot, TestInstallRequiresRootAndAbsoluteBinary, TestControlValidatesActionAndRoot

5. API Contract Specification ​

Thành phần không phục vụ API mạng. Hợp đồng gồm: lệnh CLI, cờ, mã thoát, biến môi trường, định dạng bộ phát hành và đối số script gói.

5.1. Operations (Public API) ​

Lệnh accesshub-agent (chỉ Linux, cần root)

LệnhCờHiệu ứngMã thoát
service install--binary <đường dẫn tuyệt đối> (mặc định: tệp chạy hiện tại đã giải symlink), --enableTạo tài khoản và thư mục, ghi /etc/systemd/system/accesshub-agent.service, daemon-reload, tùy chọn enable. Không start. In hướng dẫn enroll0 thành công, 1 lỗi (kể cả không phải root, đường dẫn tương đối, thiếu useradd), 2 sai cờ
service uninstall--purgedisable --now (lỗi chỉ cảnh báo), xóa unit, daemon-reload. Với --purge xóa thêm state, log, cấu hình, tài khoản0, 1, 2
uninstall--purgeĐồng nghĩa service uninstall0, 1, 2
service start, stop, restartkhôngsystemctl <hành động> accesshub-agent.service0, 1, 2
service không đối sốkhôngIn cách dùng2
service <lạ>khôngBáo hành động lạ2
Mọi lệnh trên Windowskhôngservice management is only implemented for Linux (systemd), the Windows service is planned in AGT-7 (đã sửa, OQ-P9)1

packaging/install.sh (cần root, trừ --dry-run)

Cờ hoặc biếnÝ nghĩaGhi chú
--version VBản cần cài, mặc định đọc từ <base>/latestChỉ chấp nhận A-Za-z0-9._+~-
--base-url URL, ACCESSHUB_DOWNLOAD_BASEGốc tải, https:// hoặc file:///Mặc định https://downloads.example.com/agent (giữ chỗ, D-12)
--pubkey FILE, ACCESSHUB_PUBKEY_FILEKhóa công khai PGP (gpg) hoặc PEM (cosign)Bắt buộc, trừ khi có --allow-unsigned
--allow-unsignedBỏ kiểm chữ ký, vẫn kiểm checksumIn cảnh báo
--proxy URLProxy cho tải xuống và truyền sang ACCESSHUB_PROXY_URL của agentCó thể chứa mật khẩu trên dòng lệnh (OQ-P17)
--no-startCài và enable, không khởi độngTruyền sang ACCESSHUB_NO_START=1
--dry-runTải, xác minh, in lệnh sẽ chạy, không đổi gìKhông cần root
ACCESSHUB_COLLECTOR_URL, ACCESSHUB_LICENSE, ACCESSHUB_LICENSE_FILEĐầu vào của enroll tự độngĐược export cho script gói. --token bị từ chối
Mã thoát0 thành công, 1 mọi lỗi (hàm die)Không có mã riêng cho từng lỗi

Script gói (do trình quản lý gói gọi)

ScriptĐối sốHành vi
preinstall.sh(không dùng)Tạo tài khoản nếu chưa có. Thoát 1 nếu không có useradd lẫn adduser
postinstall.sh(không dùng)Xem 7.1 và 7.4. Luôn thoát 0 ở nhánh enroll lỗi
preremove.shdeb: remove, upgrade, deconfigure, failed-upgrade. rpm: 0 gỡ, 1 nâng cấpChỉ remove, deconfigure, 0 mới disable --now
postremove.shdeb: purge và các từ khóa khác. rpm: sốChỉ purge mới xóa dữ liệu và tài khoản

Dựng phát hành

LệnhBiếnHiệu ứng
make build, make crossVERSION, COMMIT, DATE, MAX_BYTESDựng tệp chạy. cross dựng bốn mục tiêu và ghi dist/sizes.txt, thất bại khi vượt trần
make packageVERSION, COMMIT, DATE, NFPM, OUT (mặc định dist/release), SIGN_HOOKBộ phát hành đầy đủ
make snapshotnhư trênNhư package với phiên bản 0.0.0-snapshot.<sha>, ra dist/snapshot
make checksumskhôngTạo lại SHA256SUMS trong dist/release, bỏ qua latest và các tệp SHA256SUMS*

5.2. Request / Response Schema ​

Bộ phát hành (một thư mục <base>/<VERSION>/)

TệpNội dungGhi chú
accesshub-agent_<ver>_<arch>.debGói Debian, <arch> là amd64 hoặc arm64Mẫu accesshub-agent_*_${ARCH}.deb mà install.sh dùng
accesshub-agent-<ver>-1.<rpmarch>.rpmGói RPM, <rpmarch> là x86_64 hoặc aarch64Mẫu accesshub-agent-*.${RPM_ARCH}.rpm. Tên chính xác do nfpm đặt
accesshub-agent-<ver>-linux-<arch>.tar.gzTệp chạy, agent.yaml, unit, READMEKhông có script gói, cài bằng service install
install.shBộ càiSao chép từ packaging/install.sh, 0755
SHA256SUMSĐầu ra sha256sum cho *.deb *.rpm *.tar.gz install.shKhông liệt kê chính nó và chữ ký
SHA256SUMS.sigChữ ký tách rời của SHA256SUMSChỉ có khi SIGN_HOOK đặt. package.sh thất bại nếu hook không tạo tệp khác rỗng
<base>/latestMột dòng chứa chuỗi phiên bảnDo người phát hành tạo, package.sh không tạo (make checksums cố ý bỏ qua)

Unit (các chỉ thị chính)

NhómChỉ thị
Khởi độngType=simple, User, Group=accesshub-agent, ExecStart=/usr/bin/accesshub-agent run, ExecReload=/bin/kill -HUP $MAINPID, After và Wants=network-online.target
Khởi động lạiRestart=on-failure, RestartSec=5, RestartPreventExitStatus=2 3 4 5, StartLimitIntervalSec=300, StartLimitBurst=10, TimeoutStopSec=30
Thư mụcStateDirectory và LogsDirectory đều accesshub-agent, mode 0750, ReadWritePaths=/var/lib/accesshub-agent /var/log/accesshub-agent, UMask=0077
HardeningNoNewPrivileges, ProtectSystem=strict, ProtectHome, PrivateTmp, PrivateDevices, ProtectKernelTunables, ProtectKernelModules, ProtectKernelLogs, ProtectControlGroups, ProtectClock, ProtectHostname, LockPersonality, MemoryDenyWriteExecute, RestrictRealtime, RestrictSUIDSGID, RestrictNamespaces, RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX, SystemCallArchitectures=native, SystemCallFilter=@system-service, CapabilityBoundingSet= và AmbientCapabilities= rỗng
Trần tài nguyênMemoryMax=96M, CPUQuota=25%, TasksMax=128, LimitNOFILE=1024
CàiWantedBy=multi-user.target

Theo chú thích trong unit, chỉ thị mới hơn systemd trên máy (ví dụ Rocky 8) bị bỏ qua kèm cảnh báo. Điều này chưa được kiểm trên distro thật (OQ-P12).

Biến môi trường của postinstall.sh

BiếnBắt buộcKiểm traHiệu ứng
ACCESSHUB_COLLECTOR_URLCần cùng tokenBắt đầu https://, ký tự trong A-Za-z0-9._~:/?#@%+=&,-Ghi collector_url: <url> vào agent.yaml
ACCESSHUB_LICENSEHoặc token trực tiếp hoặc tệpKhông kiểm ở script (agent kiểm)Đưa vào stdin của enroll --token-stdin
ACCESSHUB_LICENSE_FILEXem trênPhải đọc đượcĐọc nội dung rồi xóa an toàn (shred -u, dự phòng rm -f) sau enroll thành công
ACCESSHUB_PROXY_URLKhôngCùng danh sách trắngGhi proxy_url: "<url>" (có dấu nháy). Sai thì bỏ qua và cảnh báo
ACCESSHUB_NO_STARTKhôngBằng 1Chỉ enable, không --now
ACCESSHUB_PKG_ROOT, ACCESSHUB_BINKhôngDành cho kiểm thửThêm tiền tố đường dẫn, đổi tệp chạy

5.3. Error Codes ​

NguồnMãÝ nghĩaXử lý
Lệnh service và uninstall0Thành công
1ErrNotRoot, đường dẫn tương đối, thiếu useradd, systemctl lỗi, lỗi ghi tệp, nền tảng không phải LinuxĐọc thông báo. Không có mã riêng (cùng họ OQ-E6)
2Thiếu hành động, hành động lạ, sai cờIn cách dùng
install.sh1Mọi lỗi qua die: thiếu curl, kiến trúc không hỗ trợ, không có dpkg lẫn rpm, tải lỗi, thiếu khóa, sai chữ ký, sai checksum, đầu vào xấuThông báo bắt đầu bằng install.sh:
Script gói0Thành công hoặc enroll lỗi (đã cảnh báo)Gói vẫn cài
1preinstall.sh không tạo được tài khoản. Mọi lệnh lỗi khác khi set -e (ví dụ chown khi tài khoản thiếu)Trình quản lý gói coi là cài lỗi
package.sh1Thiếu nfpm, SIGN_HOOK không tạo SHA256SUMS.sig, lỗi dựngXem thông báo
cross-build.sh1Một tệp chạy vượt MAX_BYTESCI cross-build đỏ
Dịch vụ run2, 3, 4, 5Không được systemd khởi động lạiSửa nguyên nhân rồi systemctl restart. Nghĩa mã: L3 Enroll mục 5.3
1 và khácĐược thử lại, tối đa 10 lần trong 300 giâySau đó unit ở trạng thái failed

5.4. Versioning ​

Đối tượngQuy tắc
Phiên bản góiTag vX.Y.Z thành X.Y.Z. Không phải chữ số đầu thì thành 0.0.0-dev.<7 ký tự đầu của commit>. Ký tự ngoài A-Za-z0-9.+~- thành dấu chấm. nfpm đổi -rc.1 thành ~rc.1 theo docs/06
Tệp chạyNhúng version.Version, Commit, Date qua -ldflags
UnitKhông có số phiên bản. Nâng cấp gói thay thế tệp unit, service install ghi đè bản ở /etc/systemd/system
install.shKhông có số phiên bản hợp đồng, cờ và biến môi trường là hợp đồng ngầm. Nằm trong bộ phát hành và được SHA256SUMS bảo vệ (cùng họ OQ-E9)
Hợp đồng môi trường của postinstall.shKhông có số phiên bản. Mọi tên biến có tiền tố ACCESSHUB_

5.5. Authz - shared responsibility & permission matrix ​

Không có xác thực ứng dụng. Kiểm soát dựa hoàn toàn vào quyền hệ điều hành.

Hành độngrootTài khoản accesshub-agentNgười dùng khác
service install, uninstall, start, stop, restartĐượcBị từ chối (ErrNotRoot)Bị từ chối
install.sh (không --dry-run)ĐượcBị từ chốiBị từ chối
install.sh --dry-runĐượcĐượcĐược (chỉ đọc mạng và thư mục tạm)
Cài và gỡ góiĐượcBị từ chốiBị từ chối (trình quản lý gói)
enroll trong postinstallChạy bằng runuser từ root sang tài khoản dịch vụLà người chạyKhông áp dụng
Đọc agent.yamlĐọc, ghiĐọc (0640 nhóm dịch vụ)Không đọc được (0640 root:accesshub-agent, OQ-P1)
Đọc credentials.jsonĐọc (root bỏ qua quyền)Đọc, ghi (0600)Bị từ chối
Đọc, ghi /var/lib/accesshub-agentĐượcĐược (0750)Bị từ chối

6. Data Schema (Physical) ​

Thành phần này ghi và xóa tệp hệ thống. Không có cơ sở dữ liệu. Mục 6.1 mô tả bố cục tệp và quyền thay cho lược đồ.

6.1. Cài đặt vật lý ​

Bảng ánh xạ

Phân hệ (3.2)Aggregate (4)StoreCấu trúc vật lý cốt lõi
Gói debServiceUnit, InstallLayout/lib/systemd/system/accesshub-agent.service 0644Unit do gói sở hữu (root)
Gói rpmServiceUnit, InstallLayout/usr/lib/systemd/system/accesshub-agent.service 0644Cùng nội dung, thư mục khác
svc.ManagerServiceUnit/etc/systemd/system/accesshub-agent.service 0644Bản do service install ghi, thắng bản của gói nếu cả hai cùng có (suy luận từ mã, OQ-P13)
GóiTệp chạy/usr/bin/accesshub-agent 0755Tệp tĩnh
GóiCấu hình/etc/accesshub-agent/agent.yaml 0640 root:accesshub-agent (nfpm.yaml), kiểu config|noreplaceKhông ghi đè khi nâng cấp. Có thể chứa proxy_url kèm mật khẩu (OQ-P1, trả lời OQ-E19)
Gói, svc.ManagerInstallLayout/var/lib/accesshub-agent 0750 accesshub-agentChứa credentials.json và wal (xem L3 Enroll, WAL)
postinstall.sh, svc.Manager, LogsDirectoryInstallLayout/var/log/accesshub-agent 0750 accesshub-agentKhông có trong nfpm.yaml (OQ-P7). Unit tạo khi chạy, script và svc tạo khi cài
GóiTài liệu/usr/share/doc/accesshub-agent/README.md 0644
preinstall.sh, svc.ManagerServiceAccountBản ghi passwd và group accesshub-agentuseradd --system --user-group --no-create-home --home-dir <state> --shell /usr/sbin/nologin

Lược đồ (tệp và quyền)

mermaid
classDiagram
  namespace He_Thong_Tep {
    class usrBin {
      path usr_bin_accesshub_agent
      mode 0755_root
    }
    class unitPkg {
      path lib_or_usr_lib_systemd_system
      mode 0644_root
      owner package
    }
    class unitManual {
      path etc_systemd_system
      mode 0644_root
      owner service_install
    }
    class etcDir {
      path etc_accesshub_agent
      mode 0755
    }
    class agentYaml {
      name agent_yaml
      mode 0644_root
      type config_noreplace
    }
    class stateDir {
      path var_lib_accesshub_agent
      mode 0750_service_account
    }
    class logDir {
      path var_log_accesshub_agent
      mode 0750_service_account
      shipped_by nfpm_no
    }
  }
  etcDir *-- agentYaml : chứa
  stateDir ..> etcDir : credentials ở state, cấu hình ở etc
  unitManual ..> unitPkg : ưu tiên cao hơn nếu cùng có

Ghi chú lược đồ: postinstall.sh và svc.Manager.ensureDirs đặt lại chmod 0750 và chown cho thư mục state và log mỗi lần chạy, còn systemd với StateDirectoryMode=0750 và LogsDirectoryMode=0750 đặt lại khi dịch vụ khởi động. set_key ghi agent.yaml qua tệp tạm agent.yaml.new.<pid> cùng thư mục rồi mv, nên thay thế nguyên tử. Tệp mới luôn 0644 và chủ sở hữu là người chạy script (root).

6.2. Phân loại dữ liệu & retention ​

Phần tử / Trường dữ liệuPhân lớp dữ liệuThời hạn lưu trữ (Retention)Cơ chế bảo vệ kỹ thuật
License trong ACCESSHUB_LICENSEBí mậtSuốt đời tiến trình cài (môi trường của apt-get, dpkg, script)Đưa vào ống, không argv. Lộ được qua /proc/<pid>/environ cho root và cùng người dùng (suy luận từ mã, OQ-P18). install.sh từ chối --token
Tệp token ACCESSHUB_LICENSE_FILEBí mậtXóa an toàn (shred -u) sau enroll thành công. Giữ nguyên nếu enroll lỗiQuyền tệp do người tạo chọn. Script chỉ kiểm đọc được
agent.yamlNội bộ, có thể chứa mật khẩu proxyTheo người vận hành. purge xóa0640 root:accesshub-agent theo gói, service install và set_key, danh sách trắng ký tự khi ghi (OQ-P1)
credentials.jsonBí mậtGiữ khi gỡ thường và nâng cấp. Xóa khi deb purge hoặc uninstall --purge. Gói rpm không có purge (OQ-P8)Thuộc tài khoản dịch vụ, 0600 (L3 Enroll)
Bộ phát hành, SHA256SUMS, chữ kýCông khaiTheo kho gói (chưa có, Q2)Chữ ký và checksum
Khóa công khai phát hànhCông khaiDo người vận hành giữTệp cục bộ, kiểm định dạng
Khóa ký riêngBí mậtNgoài agentNgoài phạm vi (AGT-11, Q3)
Nhật ký cài đặtNội bộDo trình quản lý gói và journald quyết địnhThành phần không tự ghi nhật ký cài đặt

7. Thuật toán & Luồng nghiệp vụ ​

7.1. Luồng nghiệp vụ chính (happy path) ​

Luồng 1: install.sh cài và enroll tự động

mermaid
sequenceDiagram
  participant OP as Quản trị viên
  participant INS as install.sh
  participant REL as Nơi phát hành
  participant PM as Trình quản lý gói
  participant PKG as Script gói
  participant SD as systemd

  OP->>INS: sudo ACCESSHUB_COLLECTOR_URL và TOKEN, install.sh --pubkey key
  INS->>REL: tải latest, SHA256SUMS, SHA256SUMS.sig
  INS->>INS: gpg hoặc cosign xác minh chữ ký
  INS->>INS: chọn tên gói từ SHA256SUMS đã xác minh
  INS->>REL: tải gói
  INS->>INS: sha256sum khớp dòng trong SHA256SUMS
  INS->>PM: export biến ACCESSHUB_*, apt-get hoặc dnf install gói
  PM->>PKG: preinstall rồi giải nén rồi postinstall
  PKG->>SD: daemon-reload, try-restart
  PKG->>PKG: ghi collector_url, enroll --token-stdin bằng tài khoản dịch vụ
  PKG->>SD: enable --now
  INS-->>OP: in kết quả, thoát 0

Thứ tự là bất biến: chữ ký rồi tên gói rồi checksum rồi mới gọi trình quản lý gói. Tên gói lấy từ SHA256SUMS đã xác minh nên kẻ chen được vào thư mục phát hành không đổi được gói nào được cài (INV-P8). Với --dry-run luồng dừng sau bước kiểm checksum và in lệnh cài sẽ chạy. Biến ACCESSHUB_* chỉ được export khi khác rỗng. Mã: packaging/install.sh, TestInstallVerifiesSignature, TestInstallAllowUnsignedStillChecksums.

Luồng 2: cài gói trần rồi enroll thủ công

mermaid
sequenceDiagram
  participant OP as Quản trị viên
  participant PM as Trình quản lý gói
  participant PKG as Script gói
  participant SD as systemd
  participant ENR as accesshub-agent enroll

  OP->>PM: dpkg -i hoặc rpm -U gói
  PM->>PKG: preinstall
  PKG-->>PM: tạo tài khoản accesshub-agent nếu thiếu
  PM->>PKG: postinstall không có biến môi trường
  PKG->>PKG: tạo state và log 0750 thuộc tài khoản
  PKG->>SD: daemon-reload, try-restart
  PKG-->>PM: thoát 0, không enroll, không khởi động
  OP->>ENR: sudo -u accesshub-agent accesshub-agent enroll --token-file file
  ENR-->>OP: enrolled as agent id
  OP->>SD: systemctl enable --now accesshub-agent

Cách này tách hẳn cài và cấu hình. Sau bước cuối, agent.yaml phải có collector_url (gói chỉ cài tệp mẫu có dòng này bị comment), nên quản trị viên phải sửa tệp trước khi enroll (xem luồng 8 về cái bẫy của lệnh service install). Kiểm thử: TestPostinstallWithoutEnvOnlyPreparesDirectories.

Luồng 3: service install thủ công (tệp chạy không qua gói)

mermaid
sequenceDiagram
  participant OP as Quản trị viên root
  participant CLI as serviceInstall
  participant MGR as svc.Manager
  participant OS as Hệ điều hành
  participant SD as systemd

  OP->>CLI: accesshub-agent service install --enable
  CLI->>MGR: Install(Binary, Enable)
  MGR->>MGR: kiểm root và đường dẫn tuyệt đối
  MGR->>OS: getent hoặc Lookup rồi useradd nếu chưa có
  MGR->>OS: tạo state và log 0750 chown, config 0755
  MGR->>OS: ghi etc systemd system accesshub-agent.service 0644
  MGR->>SD: systemctl daemon-reload
  MGR->>SD: systemctl enable accesshub-agent.service
  MGR-->>CLI: nil
  CLI-->>OP: hướng dẫn enroll rồi systemctl enable --now

Install không bao giờ start (INV-P2). Nó ghi agent.yaml mẫu (0640 root:accesshub-agent) khi chưa có tệp, và không bao giờ đụng tệp đã có (OQ-P3). Cờ --collector URL điền collector_url vào tệp mới. Nội dung unit là RenderUnit(Binary), tức unit nhúng với ExecStart trỏ tới đường dẫn tuyệt đối đã giải symlink. Kiểm thử: TestInstallCreatesAccountDirsUnitAndReloads, TestServiceInstallWritesUnitForThisExecutable, TestInstallWritesCollectorURLIntoNewConfigOnly, TestInstallRejectsUnsafeCollectorURL, TestServiceInstallCollectorFlag.

Luồng 4: nâng cấp gói khi dịch vụ đang chạy

mermaid
sequenceDiagram
  participant PM as Trình quản lý gói
  participant PRE as preremove
  participant PKG as preinstall và postinstall
  participant SD as systemd

  PM->>PKG: preinstall bản mới
  PKG-->>PM: tài khoản đã có, thoát 0
  PM->>PRE: preremove của bản cũ, đối số upgrade hoặc 1
  PRE-->>PM: không làm gì, dịch vụ vẫn chạy
  PM->>PM: thay tệp chạy và unit, giữ agent.yaml nhờ noreplace
  PM->>PKG: postinstall
  PKG->>SD: daemon-reload
  PKG->>SD: try-restart accesshub-agent
  SD-->>PKG: dịch vụ chạy lại bằng tệp chạy mới

try-restart chỉ khởi động lại dịch vụ đang chạy, nên nâng cấp không vô tình bật một dịch vụ đã tắt (TestPreremoveOnlyStopsOnRealRemoval kiểm phần preremove, phần try-restart được kiểm gián tiếp qua lệnh systemctl mà shim ghi lại ở TestPostinstallWithoutEnvOnlyPreparesDirectories). credentials.json không bị đụng tới (QAS-P05).

Luồng 5: gỡ gói thường rồi gỡ sạch (deb purge)

mermaid
sequenceDiagram
  participant OP as Quản trị viên
  participant PM as dpkg
  participant PRE as preremove
  participant POST as postremove
  participant SD as systemd
  participant FS as Hệ tệp

  OP->>PM: apt-get remove accesshub-agent
  PM->>PRE: preremove remove
  PRE->>SD: disable --now
  PM->>PM: xóa tệp của gói, giữ cấu hình đã sửa
  PM->>POST: postremove remove
  POST->>SD: daemon-reload
  Note over FS: state, log, config và tài khoản vẫn còn
  OP->>PM: apt-get purge accesshub-agent
  PM->>POST: postremove purge
  POST->>FS: xóa state, log, etc accesshub-agent
  POST->>FS: userdel accesshub-agent

Gỡ thường giữ credentials.json nên cài lại không cần enroll lại (QAS-P06), nhưng preremove đã disable nên dịch vụ phải được bật lại (systemctl enable --now) hoặc cài lại với đủ biến môi trường (nhánh "already enrolled" của postinstall vẫn enable --now). Điều này suy luận từ mã, chưa chạy thật. Kiểm thử: TestPostremoveKeepsDataUnlessPurge. Với rpm không có bước purge, dùng accesshub-agent uninstall --purge trước khi gỡ gói (OQ-P8, OQ-P13).

Luồng 6: package.sh dựng bộ phát hành

mermaid
sequenceDiagram
  participant DEV as Người phát hành
  participant PK as package.sh
  participant GO as go build
  participant NF as nfpm
  participant HOOK as SIGN_HOOK

  DEV->>PK: VERSION=v1.2.3 make package
  PK->>PK: suy ra pkg_version, kiểm có nfpm
  loop amd64 và arm64
    PK->>GO: CGO_ENABLED=0 go build với ldflags phiên bản
    PK->>NF: sed thay AGENT_BINARY rồi nfpm package deb và rpm
    PK->>PK: tạo tar.gz gồm tệp chạy, agent.yaml, unit, README
  end
  PK->>PK: chép install.sh, sha256sum ra SHA256SUMS
  PK->>HOOK: SIGN_HOOK đường dẫn SHA256SUMS nếu có
  HOOK-->>PK: SHA256SUMS.sig khác rỗng
  PK-->>DEV: liệt kê thư mục phát hành

Khối lặp thực tế chạy hai lần (hai kiến trúc), mỗi lần dựng hai gói và một tar.gz. Không có kiểm thử tự động cho luồng này (mục 14).

7.2. Luồng thay thế và lỗi ​

Luồng 7: chữ ký hoặc checksum sai, install.sh dừng trước khi cài

mermaid
sequenceDiagram
  participant OP as Quản trị viên
  participant INS as install.sh
  participant REL as Nơi phát hành
  participant PM as Trình quản lý gói

  OP->>INS: install.sh --pubkey key
  INS->>REL: tải SHA256SUMS và SHA256SUMS.sig
  INS->>INS: gpg hoặc cosign verify
  INS-->>OP: SIGNATURE VERIFICATION FAILED, thoát 1
  Note over INS: hoặc sau khi tải gói, sha256 lệch thì báo CHECKSUM MISMATCH và thoát 1
  Note over PM: trình quản lý gói không bao giờ được gọi

Hai kiểm tra là độc lập: --allow-unsigned chỉ bỏ kiểm chữ ký, vẫn kiểm checksum (TestInstallAllowUnsignedStillChecksums). Thiếu cả khóa lẫn --allow-unsigned thì dừng ngay với thông báo nói cách khắc phục (TestInstallRefusesWithoutKeyOrOptOut).

Luồng 8: cài thủ công bằng service install nhưng chưa có collector_url

mermaid
sequenceDiagram
  participant OP as Quản trị viên root
  participant MGR as svc.Manager
  participant SD as systemd
  participant RUN as accesshub-agent run

  OP->>MGR: service install --enable
  MGR-->>OP: đã ghi unit, không ghi agent.yaml
  OP->>SD: systemctl start accesshub-agent
  SD->>RUN: ExecStart run
  RUN-->>SD: thoát mã 3, thiếu collector_url
  Note over SD: mã 3 nằm trong RestartPreventExitStatus nên không thử lại
  SD-->>OP: dịch vụ ở trạng thái failed
  Note over OP: sửa agent.yaml, enroll bằng tài khoản dịch vụ, rồi systemctl restart

Đây là cái bẫy của đường thủ công (OQ-P3). Đường gói không gặp vì postinstall ghi collector_url trước khi enable --now, còn đường trần (luồng 2) thì người vận hành tự sửa tệp. Bản thân việc dịch vụ dừng hẳn là đúng thiết kế (FR-P03), phần hướng dẫn đã bổ sung: service install ghi agent.yaml mẫu (nếu chưa có), nhận --collector URL, và thông điệp in ra nhắc phải đặt collector_url trước khi enroll. Dịch vụ vẫn failed (mã 3) nếu người vận hành bỏ qua bước đó. Chưa chạy trên máy thật.

Luồng 9: enroll trong postinstall thất bại, gói vẫn cài

mermaid
sequenceDiagram
  participant PM as Trình quản lý gói
  participant PKG as postinstall
  participant ENR as accesshub-agent enroll
  participant OP as Quản trị viên

  PM->>PKG: postinstall có đủ URL và token
  PKG->>PKG: ghi collector_url vào agent.yaml
  PKG->>ENR: printf token qua ống, runuser enroll --token-stdin
  ENR-->>PKG: mã thoát khác 0 (token hết hạn, mạng lỗi)
  PKG-->>PM: cảnh báo enroll failed, thoát 0
  Note over PKG: không enable --now, tệp token được giữ để thử lại
  PM-->>OP: gói cài thành công
  Note over OP: sửa nguyên nhân rồi chạy sudo -u accesshub-agent accesshub-agent enroll

collector_url đã được ghi trước khi enroll nên lần thử lại thủ công không cần sửa tệp. Mã thoát của enroll được bỏ qua ở mức script: mọi mã khác 0 cùng xử lý như nhau (ý nghĩa từng mã xem L3 Enroll mục 5.3). Kiểm thử: TestPostinstallEnrollFailureDoesNotFailPackageOrStart.

Các tình huống thay thế và lỗi khác

Tình huốngĐiều kiệnHành viNơi hiện thực hoặc kiểm thử
Đã enroll trước đócredentials.json tồn tại khi postinstall có biếnCảnh báo, không enroll lại, vẫn ghi khóa YAML và enable --now. Tệp token (nếu có) được giữ, không bị xóaTestPostinstallKeepsExistingCredentials. Việc giữ tệp token suy luận từ mã, OQ-P15
URL hoặc proxy sai dạngKhông https:// hoặc có ký tự ngoài danh sách trắngURL: bỏ qua cả enroll, không sửa agent.yaml. Proxy: bỏ qua riêng proxy, vẫn enrollTestPostinstallRejectsUnsafeValues
Chỉ có URL hoặc chỉ có tokenThiếu một nửaCảnh báo, bỏ qua enroll, thoát 0TestPostinstallNeedsBothURLAndToken
Tệp token không đọc đượcACCESSHUB_LICENSE_FILE không tồn tại hoặc không đọc đượcCảnh báo, bỏ qua enroll, thoát 0postinstall.sh (chưa có kiểm thử riêng)
--no-startACCESSHUB_NO_START=1Chỉ enable, không --nowTestPostinstallNoStartOnlyEnables
Không có useradd lẫn adduserBản phân phối tối giảnpreinstall.sh thoát 1, gói không cài. service install thì báo lỗi nói cách tự tạo tài khoảnTestInstallFailsClearlyWithoutUseradd (chỉ nhánh Go). Nhánh script chưa có kiểm thử
Không có runuserHệ rất cũDự phòng su -s /bin/sh -cChưa có kiểm thử (mục 14)
Không có systemctlContainer, hệ không systemdScript bỏ qua daemon-reload và try-restart. Nhánh cuối systemctl enable lỗi thì chỉ cảnh báo, gói vẫn càipostinstall.sh (suy luận từ mã). svc.Manager trả lỗi
Chạy enroll bằng root (tay)Không đi qua postinstallcredentials.json thuộc root 0600, dịch vụ không đọc được, run thoát mã 1 và được thử lại cho tới khi hết hạn mức (OQ-E5, OQ-P2)L3 Enroll mục 11.1
Không phải rootservice install, start, stop, restart, uninstall, install.shTừ chối, thoát 1TestInstallRequiresRootAndAbsoluteBinary, TestControlValidatesActionAndRoot, TestServiceNeedsRootAndAKnownAction
Đường dẫn tệp chạy tương đối--binary relative/agentTừ chốiTestServiceInstallHonorsBinaryFlagAndRejectsRelative
Gỡ dịch vụ chưa nạpdisable --now báo lỗiChỉ cảnh báo, tiếp tục xóa unitTestUninstallToleratesServiceThatIsNotLoaded
Hai bản unitCài gói rồi chạy service install/etc/systemd/system thắng /lib hoặc /usr/lib. uninstall chỉ xóa bản /etc (OQ-P13)Suy luận từ mã và quy tắc ưu tiên của systemd, chưa chạy
uninstall --purge sau cài góiGói vẫn cònXóa luôn /etc/accesshub-agent thuộc gói, thư mục state, log và tài khoản, còn tệp gói nằm lạiTestUninstallKeepsDataUnlessPurge (kiểm xóa, không kiểm kịch bản gói)
rpm gỡ không purgeDùng rpm -e hoặc dnf removeDữ liệu và tài khoản còn lại mãi (OQ-P8)postremove.sh
Crash lặprun thoát mã 1 liên tụcThử lại cách 5 giây, sau 10 lần trong 300 giây thì unit failedUnit. Không có kiểm thử hành vi
Cài từ tar.gzKhông có trình quản lý góiKhông có script gói: phải tự service install, tự viết agent.yaml, tự enrollpackage.sh (OQ-P14)
Tải lỗicurl thất bạidie "download failed: <url>", thoát 1install.sh
Kiến trúc hoặc công cụ gói lạKhông phải x86_64 hay aarch64, không có dpkg lẫn rpmdie, thoát 1install.sh
Đầu vào xấu--token, phiên bản có ký tự lạ, URL không https:// hoặc file://, tên gói có /die, thoát 1TestInstallRejectsUnsafeInput
SIGN_HOOK hỏngHook không tạo SHA256SUMS.sig khác rỗngpackage.sh thoát 1, bộ phát hành đã dựng nhưng không có chữ kýpackage.sh (chưa có kiểm thử)
Vượt trần kích thướcTệp chạy lớn hơn MAX_BYTEScross-build.sh thoát 1, CI đỏJob cross-build

7.3. Máy trạng thái ​

Mỗi sơ đồ chỉ mô hình hóa một thực thể. Nhãn cạnh theo dạng trigger [guard] / event.

7.3.1. Dịch vụ systemd trên một máy

mermaid
stateDiagram-v2
  [*] --> Absent
  Absent --> Installed : service install hoặc cài gói / ghi unit, daemon-reload
  Installed --> Enabled : enable / liên kết vào multi-user.target
  Installed --> Running : enable --now hoặc start [có agent.yaml và credentials] / run chạy
  Enabled --> Running : start hoặc khởi động máy [có agent.yaml và credentials] / run chạy
  Installed --> Failed : start [thiếu cấu hình hoặc danh tính] / run thoát mã 3 hoặc 4
  Enabled --> Failed : start [thiếu cấu hình hoặc danh tính] / run thoát mã 3 hoặc 4
  Running --> Running : run thoát mã 1 [dưới 10 lần trong 300 giây] / chạy lại sau 5 giây
  Running --> Failed : run thoát mã 2, 3, 4, 5 / không thử lại
  Running --> Failed : run thoát mã 1 [đủ 10 lần trong 300 giây] / start limit hit
  Running --> Stopped : stop hoặc SIGTERM / run thoát mã 0 trong 30 giây
  Stopped --> Running : start / run chạy
  Failed --> Running : restart [đã sửa nguyên nhân] / run chạy
  Running --> Running : try-restart khi nâng cấp / chạy bằng tệp mới
  Installed --> Absent : uninstall / xóa unit
  Enabled --> Absent : uninstall / disable, xóa unit
  Running --> Absent : uninstall / disable --now, xóa unit
  Stopped --> Absent : uninstall / disable, xóa unit
  Failed --> Absent : uninstall / disable, xóa unit
Đường (trigger)Nơi hiện thựcKiểm thử
Absent sang Installedsvc.Manager.Install, nfpm.yaml (unit) và postinstall.sh (daemon-reload)TestInstallCreatesAccountDirsUnitAndReloads, TestNfpmSourcesExist
Installed sang Enabledsystemctl enable, cờ --enable hoặc ACCESSHUB_NO_START=1TestInstallKeepsExistingAccountAndSkipsEnableByDefault, TestPostinstallNoStartOnlyEnables
Sang Runningsystemctl enable --now hoặc startTestPostinstallEnrollsThroughStdinAndStarts, TestServiceControlAndUninstall
Sang Failed với mã 3 hoặc 4 (thiếu điều kiện)Unit RestartPreventExitStatus, mã thoát của run (L3 Enroll)Chỉ kiểm chuỗi trong unit: TestPackagedUnitCarriesRequiredHardening. Chưa có kiểm thử hành vi. service install đã ghi mẫu và nhắc collector_url (OQ-P3)
Running sang Running (thử lại) và Running sang Failed (vượt hạn mức)Unit Restart=on-failure, RestartSec=5, StartLimitIntervalSec=300, StartLimitBurst=10Chưa có kiểm thử hành vi (mục 14)
Running sang StoppedControl("stop"), SIGTERM tới run (TimeoutStopSec=30)TestServiceControlAndUninstall (kiểm lệnh, không đo thời gian dừng)
Failed sang RunningControl("restart") sau khi sửaTestServiceControlAndUninstall
Running sang Running (nâng cấp)postinstall.sh try-restartChưa có kiểm thử riêng. Xem luồng 4
Sang Absentsvc.Manager.Uninstall, preremove.sh kèm gói xóa tệpTestUninstallKeepsDataUnlessPurge, TestUninstallToleratesServiceThatIsNotLoaded, TestPreremoveOnlyStopsOnRealRemoval

Trạng thái Failed ở đây là trạng thái của unit do systemd giữ, không lưu ở đâu trong mã của thành phần này. Mọi trạng thái đều là suy luận từ unit và mã thoát, chưa quan sát trên systemd thật ngoài kiểm tra cú pháp.

7.3.2. Vòng đời dữ liệu của một lần cài (theo gói)

mermaid
stateDiagram-v2
  [*] --> Absent
  Absent --> Unenrolled : cài gói [không có biến hoặc enroll lỗi] / tài khoản và thư mục, chưa enroll
  Absent --> Enrolled : cài gói [URL và token hợp lệ, enroll thành công] / enroll, enable --now
  Unenrolled --> Enrolled : enroll thủ công / credentials.json 0600
  Enrolled --> Enrolled : nâng cấp gói / try-restart, giữ dữ liệu
  Unenrolled --> Unenrolled : nâng cấp gói / giữ cấu hình
  Enrolled --> Removed : remove [deb hoặc rpm] / disable --now, giữ dữ liệu
  Unenrolled --> Removed : remove / giữ dữ liệu
  Removed --> Enrolled : cài lại [credentials.json còn] / không cần enroll lại
  Removed --> Purged : purge [chỉ deb] / xóa state, log, etc, tài khoản
  Enrolled --> Purged : purge [chỉ deb] / xóa state, log, etc, tài khoản
  Unenrolled --> Purged : purge [chỉ deb] / xóa state, log, etc, tài khoản
  Purged --> Absent : hoàn tất / không còn gì
Đường (trigger)Nơi hiện thựcKiểm thử
Absent sang Unenrolledpreinstall.sh, postinstall.sh (nhánh không có biến hoặc enroll lỗi)TestPostinstallWithoutEnvOnlyPreparesDirectories, TestPostinstallEnrollFailureDoesNotFailPackageOrStart
Absent sang Enrolledpostinstall.sh (nhánh enroll thành công)TestPostinstallEnrollsThroughStdinAndStarts
Unenrolled sang Enrolled (thủ công)accesshub-agent enroll (L3 Enroll)Xem L3 Enroll mục 14
Nâng cấpnfpm.yaml (config|noreplace), postinstall.shTestPostinstallKeepsExistingCredentials, TestPostinstallReplacesExistingCollectorURLOnce
Sang Removedpreremove.sh, postremove.shTestPreremoveOnlyStopsOnRealRemoval, TestPostremoveKeepsDataUnlessPurge
Removed sang Enrolled (cài lại)Dữ liệu còn, postinstall.sh nhánh "already enrolled"TestPostinstallKeepsExistingCredentials. Việc dịch vụ chưa được bật lại là suy luận từ mã
Sang Purgedpostremove.sh nhánh purgeTestPostremoveKeepsDataUnlessPurge

Đường uninstall --purge (không qua gói) không có trong sơ đồ vì nó xóa dữ liệu nhưng để nguyên tệp gói, tạo ra một trạng thái không thuộc vòng đời này (gói còn, dữ liệu và tài khoản mất, OQ-P13).

7.4. Thuật toán và quyết định thiết kế ​

7.4.1. Một nguồn unit và RenderUnit ​

Vấn đề: hai đường cài (gói và service install) đều cần một unit, và nếu hai bản lệch nhau thì hardening chỉ có trên một đường mà không ai hay.

Giải pháp: tệp internal/svc/accesshub-agent.service là nguồn duy nhất. go:embed nhúng nó vào tệp chạy (PackagedUnit()), còn nfpm.yaml trỏ thẳng src tới cùng tệp. RenderUnit(bin) chỉ thay tiền tố ExecStart=/usr/bin/accesshub-agent bằng ExecStart=<bin> và trả nguyên bản khi bin rỗng hoặc bằng đường dẫn mặc định. ExecReload dùng /bin/kill -HUP $MAINPID nên không phụ thuộc đường dẫn tệp chạy.

Trade-off: thay chuỗi theo tiền tố đơn giản và kiểm thử được (TestRenderUnitRewritesOnlyTheBinary), nhưng không thoát ký tự: đường dẫn có khoảng trắng hoặc % sẽ làm hỏng hoặc đổi nghĩa dòng ExecStart (OQ-P6). ReadWritePaths cũng cố định theo đường dẫn mặc định, nên state_dir hay log.file tùy chỉnh ngoài hai thư mục này sẽ bị ProtectSystem=strict chặn ghi (OQ-P5). MemoryMax=96M là trần cứng của cgroup còn limits.memory_limit là mềm (GOMEMLIMIT) và cấu hình được tới 4 GiB, nên cấu hình lớn hơn 96 MiB sẽ bị giết thay vì tự nén (OQ-P4).

7.4.2. Ghi khóa vào agent.yaml an toàn ​

Vấn đề: giá trị từ biến môi trường của người cài được ghi vào tệp YAML. Ký tự xuống dòng, dấu nháy hay $ có thể chèn khóa khác vào cấu hình, còn ghi dở có thể để lại tệp nửa vời.

Giải pháp (valid_value, set_key trong postinstall.sh): (1) collector_url phải bắt đầu https:// và có ít nhất một ký tự sau đó. (2) Cả URL và proxy chỉ được chứa A-Za-z0-9._~:/?#@%+=&,- (case với mẫu phủ định). Sai thì bỏ qua cả enroll (URL) hoặc chỉ bỏ proxy. (3) set_key tạo agent.yaml.new.<pid> cùng thư mục: nếu khóa đã có thì awk thay đúng dòng bắt đầu bằng key:, nếu chưa thì nối thêm dòng, rồi chmod 0644 và mv đè. Proxy được đặt trong dấu nháy kép.

Trade-off: danh sách trắng loại cả những URL hợp lệ có ký tự lạ (ví dụ mật khẩu proxy có !). set_key chỉ tìm khóa ở cột đầu của dòng, nên khóa lồng hay khóa đã comment không bị thay mà bị nối thêm dòng mới. Ghi nguyên tử nhưng không khóa tệp, hai lần cài song song là hiếm và không được hỗ trợ. Tệp mới luôn 0640 root:accesshub-agent, và postinstall siết tệp đã có về cùng quyền (OQ-P1).

7.4.3. Enroll trong postinstall ​

Vấn đề: cần enroll không tương tác mà token không lộ qua danh sách tiến trình, credentials.json phải thuộc tài khoản dịch vụ, và lỗi mạng hay token sai không được làm hỏng việc cài gói (nếu gói hỏng thì hàng loạt máy ở trạng thái nửa cài).

Giải pháp: (1) Thoát sớm nếu không có biến nào, hoặc chỉ có một nửa. (2) Chọn run_as: runuser -u accesshub-agent -- nếu có, nếu không thì su -s /bin/sh -c 'exec "$0" "$@"'. (3) printf '%s\n' "$token" | run_as BIN enroll --token-stdin, tức token đi qua ống và argv chỉ có cờ. (4) Thành công thì xóa tệp token bằng shred -u (dự phòng rm -f). (5) Lỗi thì in cảnh báo kèm lệnh thử lại và exit 0. (6) unset token, rồi enable --now (hoặc enable khi ACCESSHUB_NO_START=1). Lỗi systemctl ở bước cuối chỉ cảnh báo.

Trade-off: token vẫn nằm trong biến môi trường của cả quá trình cài (apt-get, dpkg, các script), nên đọc được qua /proc/<pid>/environ của root và của cùng người dùng (OQ-P18). Dùng tệp token tránh được điều này ở phía người gọi nhưng install.sh vẫn chuyển tiếp tên biến. Khi nhánh "already enrolled" chạy, tệp token không bị xóa (OQ-P15). Nuốt mọi lỗi enroll giúp gói luôn cài được nhưng nghĩa là pipeline tự động hóa không biết enroll hỏng nếu chỉ xem mã thoát của gói, phải đọc log hoặc kiểm systemctl is-active.

7.4.4. Chuỗi xác minh của install.sh ​

Vấn đề: kẻ chiếm được kho tải có thể thay gói bằng mã độc chạy bằng root. Nếu tên gói hay checksum lấy từ chính thư mục bị chiếm thì kiểm tra vô nghĩa.

Giải pháp: (1) Tải SHA256SUMS và SHA256SUMS.sig. (2) Có --pubkey thì nhận dạng khóa: PGP thì gpg --verify trong GNUPGHOME tạm, PEM thì cosign verify-blob. Không có khóa và không có --allow-unsigned thì dừng. (3) Chọn tên gói bằng awk trên SHA256SUMS đã xác minh theo mẫu của kiến trúc và định dạng, và từ chối tên có / hay ký tự ngoài A-Za-z0-9._+~-. (4) Tải đúng gói đó, tính sha256sum (hoặc shasum -a 256) và so với dòng khớp tên trong SHA256SUMS. Lệch hay thiếu thì dừng. (5) Mới export biến và gọi trình quản lý gói.

Trade-off: toàn bộ độ tin cậy dồn vào khóa công khai do người vận hành cung cấp và cách họ phân phối nó (chưa có kênh, Q3 của L2). Chữ ký chỉ phủ SHA256SUMS nên install.sh tải kèm cũng phải nằm trong danh sách (đã có trong package.sh) nhưng người chạy curl | sh bản install.sh chưa xác minh thì mất bảo vệ: hướng dẫn nên tải, kiểm rồi mới chạy (OQ-P10). Giá trị mặc định của --base-url là địa chỉ giữ chỗ nên trên thực tế bắt buộc truyền --base-url (OQ-P10).

7.4.5. Suy ra phiên bản gói ​

Vấn đề: deb và rpm đòi phiên bản bắt đầu bằng chữ số và bị kén ký tự, trong khi git describe có thể cho v1.2.3, 9d76488-dirty hay v1.2.3-4-gabc-dirty.

Giải pháp (package.sh): (1) version lấy từ VERSION hoặc git describe --tags --always --dirty hoặc dev. (2) Bỏ tiền tố v. (3) Không bắt đầu bằng chữ số thì đặt 0.0.0-dev.<7 ký tự đầu của commit>. (4) Đổi mọi ký tự ngoài A-Za-z0-9.+~- thành dấu chấm. make snapshot dùng 0.0.0-snapshot.<sha>. Tệp chạy vẫn nhúng chuỗi version gốc qua -ldflags, còn gói mang pkg_version.

Trade-off: một cây làm việc bẩn trên đúng tag vẫn cho ra phiên bản 1.2.3-dirty (chữ số đầu), có thể bị nhầm là bản phát hành. latest không do package.sh tạo nên khâu đẩy phiên bản lên "kênh" do người phát hành tự làm (AGT-11). Quy tắc này chưa có kiểm thử tự động.

7.4.6. Giữ và xóa dữ liệu khi gỡ ​

Vấn đề: gỡ rồi cài lại (hay nâng cấp) không được bắt enroll lại và không được làm mất agent.yaml đã chỉnh, nhưng người muốn gỡ sạch vẫn cần cách xóa hết kể cả bí mật.

Giải pháp: agent.yaml là config|noreplace nên nâng cấp không đè, và gỡ thường không xóa tệp cấu hình đã sửa. preremove.sh chỉ dừng khi đối số là remove, deconfigure hoặc 0. postremove.sh chỉ xóa ba thư mục và tài khoản khi đối số là purge. Đường thủ công: uninstall giữ dữ liệu, uninstall --purge xóa thư mục state, log, cấu hình và tài khoản.

Trade-off: rpm không có khái niệm purge trong script, nên gỡ sạch rpm cần hai bước theo thứ tự (uninstall --purge trước khi gỡ gói) mà dễ quên (OQ-P8). uninstall --purge không biết mình có nằm cạnh gói hay không, nên sẽ xóa cả /etc/accesshub-agent của gói (OQ-P13). Gỡ thường để lại tài khoản hệ thống và thư mục /var/log/accesshub-agent mồ côi vì nfpm không khai báo nó, còn tài khoản thì cố ý giữ để tệp trong state còn chủ hợp lệ (OQ-P7).

7.4.7. Chính sách khởi động lại theo mã thoát ​

Vấn đề: khởi động lại vô hạn một tiến trình hỏng vì cấu hình sẽ tạo nhật ký ồn và đốt CPU, nhưng không khởi động lại thì lỗi tạm thời (mạng, đĩa) làm mất thu thập.

Giải pháp: Restart=on-failure, RestartSec=5. Mã 2 (dùng sai), 3 (cấu hình), 4 (chưa enroll), 5 (enroll bị từ chối) nằm trong RestartPreventExitStatus vì chờ không tự khỏi được. Mã khác (kể cả 1) được thử lại, tối đa 10 lần trong 300 giây (StartLimitIntervalSec, StartLimitBurst) rồi unit failed. Mã 6 (không có kết nối) chỉ do enroll trả, run không dùng. TimeoutStopSec=30 cho run thời gian dừng êm (runtime có hạn 10 giây riêng, L3 WAL và Sender).

Trade-off: mã 1 gộp nhiều nguyên nhân, trong đó credentials.json quyền rộng hay thuộc root (OQ-E5, OQ-E6) là lỗi không tự khỏi nhưng vẫn bị thử lại 10 lần rồi mới dừng. Sau khi failed không có gì tự đưa dịch vụ trở lại (cần systemctl restart), và thiếu khối OnFailure= nên không có cảnh báo (mục 13.3).


8. Xử lý lỗi ​

8.1. Xử lý các nhánh lỗi (error branches) ​

NhánhĐiều kiệnXử lýQuan sát
Không phải rootservice install, uninstall, start, stop, restart, install.shErrNotRoot hoặc die, thoát 1stderr
Đường dẫn tệp chạy không tuyệt đối--binaryTừ chối, thoát 1stderr
Hành động service lạservice fooIn cách dùng, thoát 2stderr
Không có useraddsvc.Manager.ensureAccountLỗi nói cách tự tạo tài khoản, thoát 1stderr
Không có useradd và adduserpreinstall.shIn lỗi, thoát 1, gói không càistderr của trình quản lý gói
systemctl lỗienable, start, stop, restart, daemon-reload trong svc.ManagerTrả lỗi, thoát 1 (trừ disable --now và daemon-reload khi gỡ: cảnh báo)stderr
systemctl lỗi trong scriptMọi lời gọi trong postinstall, preremove, postremoveNuốt lỗi, postinstall cảnh báo khi enable --now lỗistderr
Thiếu khóa và không --allow-unsignedinstall.shdie, thoát 1stderr
Chữ ký saigpg hoặc cosignSIGNATURE VERIFICATION FAILED, thoát 1 (luồng 7)stderr
Checksum lệch hoặc thiếuSau khi tải góiCHECKSUM MISMATCH, thoát 1 (luồng 7)stderr
Tên gói không có trong SHA256SUMSSai kiến trúc hoặc định dạngno package matching ..., thoát 1stderr
Tải lỗicurl thất bạidownload failed: <url>, thoát 1stderr
Đầu vào xấuLuồng 7 bảngdie, thoát 1stderr
URL hoặc proxy sai dạng trong postinstallvalid_valueBỏ qua enroll (URL) hoặc proxy, thoát 0stderr của trình quản lý gói
Enroll lỗi trong postinstallLuồng 9Cảnh báo, thoát 0, không khởi độngstderr của trình quản lý gói
run thiếu điều kiệnLuồng 8Thoát mã 3 hoặc 4, systemd không thử lạijournald, systemctl status
SIGN_HOOK không ra chữ kýpackage.shThoát 1stderr
Tệp chạy vượt trầncross-build.shThoát 1, CI đỏNhật ký CI, dist/sizes.txt

8.2. Fail-fast ​

Điều kiệnHành viMã thoát hoặc lỗi
Không phải rootKhông làm gìErrNotRoot, mã 1
Đường dẫn tệp chạy tương đốiKhông ghi unitMã 1
Hành động hoặc đối số service saiIn cách dùngMã 2
Thiếu useradd (đường Go)Không ghi gì, báo cách tự tạoMã 1
Thiếu khóa công khai và không --allow-unsignedDừng trước khi tải góiThoát 1
Chữ ký hay checksum saiDừng trước khi gọi trình quản lý góiThoát 1
--token trên dòng lệnhTừ chối ngay khi phân tích đối sốThoát 1
set -eu trong script góiLệnh lỗi hay biến chưa đặt thì dừngScript thoát khác 0 (cài lỗi), trừ chỗ có || true hay nhánh exit 0
Phiên bản hay tên gói có ký tự lạTừ chốiThoát 1

8.3. Race conditions ​

Tình huốngCơ chế hoặc hậu quảGhi chú
Hai postinstall song songTrình quản lý gói giữ khóa riêng (dpkg, rpm), nên thực tế không xảy raKhông cần xử lý
set_key ghi đè trong khi người vận hành sửa tay agent.yamlTệp tạm cùng thư mục rồi mv, nên sửa tay giữa chừng bị mất hoặc thắng tùy thứ tựHiếm, chấp nhận
try-restart đúng lúc dịch vụ đang ghi WALSIGTERM rồi dừng êm trong TimeoutStopSec=30, WAL bền nhờ tệp, xem L3 WAL và SenderKhông có tranh chấp dữ liệu mới từ thành phần này
service install chạy khi gói đang càiHai bên cùng ghi thư mục và chownKhông khóa. Hiếm, thao tác thủ công
enroll thủ công khi postinstall đang chạyenroll từ chối nếu credentials.json đã có, bên ghi sau thắng nếu cả hai qua kiểm traCùng họ OQ-E15
Gỡ gói khi dịch vụ đang khởi động lạipreremove disable --now dừng đơn vị đang thử lạiAn toàn (suy luận từ hành vi systemd)
Tải latest rồi tải gói trong lúc phát hành mới ghiThư mục phiên bản có thể chưa đủ tệpinstall.sh thất bại ở bước tải hoặc checksum, không cài nửa vời

9. Suy thoái dịch vụ & Khả năng phục hồi ​

9.1. Ma trận suy thoái theo phụ thuộc ​

Phụ thuộcLỗiSuy thoáiBảo vệPhục hồi
Nơi phát hành (install.sh)Không tới được, thiếu tệpKhông cài được. Máy đã cài không bị ảnh hưởngdie rõ tên URLThủ công: thử lại hoặc dùng --base-url file:// (bản sao cục bộ)
systemdKhông có (container)Script bỏ qua daemon-reload, try-restart. enable lỗi chỉ cảnh báo. service install báo lỗicommand -v systemctl trong scriptChạy accesshub-agent run bằng cách khác (ngoài phạm vi)
useradd và adduserKhông cópreinstall thoát 1Thông báo rõTạo tài khoản tay rồi cài lại
runuserKhông cóDự phòng sucommand -v runuserKhông cần
shredKhông cóXóa tệp token bằng rm -fcommand -v shredKhông cần
gpg hoặc cosignKhông có nhưng khóa cần nódie, không càiKiểm command -vCài công cụ hoặc dùng --allow-unsigned (kiểm thử)
sha256sum và shasumCả hai thiếudieKiểm command -vCài công cụ
curlKhông códieKiểm đầuCài curl
Collector (lúc enroll trong postinstall)Không tới đượcGói cài, chưa enroll (luồng 9)Thoát 0Thủ công: chạy lại enroll
Hệ tệp /var/lib, /var/logĐầy, chỉ đọcchown hay mkdir lỗi dưới set -e thì cài lỗiset -euThủ công
Tài khoản accesshub-agent bị xóa tayGỡ tài khoản sau khi càichown trong postinstall lỗi, cài lỗi. Dịch vụ không chạyKhông cópreinstall tạo lại ở lần cài kế
Kho gói (apt, yum)Chưa cóChỉ phát hành dạng tệpKhông áp dụng (AGT-11)Chưa có

9.2. Backup, DR, RTO và RPO ​

Thành phần không giữ dữ liệu riêng: mọi thứ nó tạo (unit, tài khoản, thư mục) tái tạo được bằng cài lại. Dữ liệu đáng giữ nằm ở thành phần khác (credentials.json ở L3 Enroll, WAL ở L3 WAL và Sender). Cấu hình agent.yaml nên nằm trong quản lý cấu hình của đội vận hành.

Chỉ sốGiá trịGhi chú
Khôi phục máy mất agentCài lại gói rồi enroll lại (token mới) hoặc giữ credentials.json nếu còncredentials.json không có bản sao lưu
RTO cài lại một máyTheo thời gian tải gói cộng càiChưa đo, không đề xuất con số
RPOKhông áp dụngKhông có dữ liệu do thành phần này sở hữu
Nâng cấp lỗi, muốn quay lạiCài lại bản cũ bằng install.sh --version, vì agent.yaml và danh tính còn nguyênChưa có kiểm tra sức khỏe sau nâng cấp hay tự quay lại (OQ-P19)
Mất khóa ký phát hànhNgoài phạm vi, thuộc hệ phát hành (Q3)

10. Đồng thời & Toàn vẹn dữ liệu ​

10.1. Ranh giới giao dịch ​

Không có cơ sở dữ liệu. Các đơn vị nguyên tử:

Đơn vịRanh giớiĐảm bảo
Ghi agent.yamlTệp tạm agent.yaml.new.<pid>, chmod, mvĐọc thấy trọn bản cũ hoặc trọn bản mới
Ghi unit (service install)os.WriteFile trực tiếp vào đích, 0644Không nguyên tử: mất điện giữa chừng có thể để lại unit cụt (hiếm, unit nhỏ)
Cài góiDo dpkg hoặc rpm đảm nhiệm, postinstall nằm trong giao dịch của họset -e lỗi thì gói ở trạng thái cấu hình dở, dpkg --configure -a chạy lại được (suy luận, chưa thử)
Xóa dữ liệu khi purgerm -rf ba thư mục rồi userdelKhông nguyên tử. Dừng giữa chừng để lại thư mục còn, tài khoản còn
Phát hànhrm -rf thư mục đầu ra rồi dựngBộ phát hành trước bị xóa ngay khi bắt đầu. Dựng lỗi giữa chừng thì không còn bộ nào

10.2. Cơ chế đồng thời ​

Cơ chếNơi dùngMục đích
Khóa của dpkg và rpmCài, nâng cấp, gỡChặn hai lần cài cùng lúc
Ghi tệp tạm rồi mvset_keyThay thế nguyên tử agent.yaml
trap dọn thư mục tạminstall.sh (cleanup)Xóa thư mục làm việc và GNUPGHOME tạm khi thoát
Không có khóa liên tiến trìnhservice install, uninstallXem 8.3

11. Bảo mật ​

11.1. Bảo mật ba lớp ​

LớpBiện phápBằng chứng
Kênh truyềninstall.sh chỉ tải qua https hoặc file (curl --proto '=https,file' --tlsv1.2), từ chối --base-url khácinstall.sh, TestInstallRejectsUnsafeInput
Danh tính và bí mậtToken không qua argv (install.sh từ chối --token, postinstall dùng ống). Giá trị ghi YAML qua danh sách trắng. Chữ ký và checksum trước khi cài. Tên gói từ danh sách đã xác minhTestInstallRejectsUnsafeInput, TestPostinstallEnrollsThroughStdinAndStarts, TestPostinstallRejectsUnsafeValues, TestInstallVerifiesSignature
Giam tiến trình và dữ liệu nghỉUnit: không capability, NoNewPrivileges, ProtectSystem=strict, bộ lọc syscall, ba họ địa chỉ, trần tài nguyên, UMask=0077. State và log 0750 thuộc tài khoản dịch vụTestPackagedUnitCarriesRequiredHardening, systemd-analyze verify (thủ công, một lần)

Các điểm yếu còn lại, nêu thẳng (R-03):

  • (Đã sửa) trước đây agent.yaml mặc định 0644 root:root nên mọi người dùng trên máy đọc được, trong khi nó có thể chứa proxy_url kèm mật khẩu (OQ-P1, trả lời OQ-E19). Đã xử lý: gói, service install và set_key đặt 0640 root:accesshub-agent, postinstall siết cả tệp cài từ trước (OQ-P1).
  • Bộ phát hành chưa có kho, khóa ký hay CI ký. Cho tới khi có, mọi bảo đảm chuỗi cung ứng phụ thuộc người vận hành tự truyền --pubkey (Q2, Q3, D-12).
  • --proxy URL đi qua argv của install.sh nên mật khẩu proxy lộ trong danh sách tiến trình (OQ-P17). Token nằm trong biến môi trường của cả quá trình cài (OQ-P18).
  • Cờ MemoryDenyWriteExecute và bộ lọc syscall chưa được kiểm tra bằng systemd-analyze security hay kiểm thử xâm nhập, chỉ kiểm cú pháp (QAS-P03).
  • RenderUnit không thoát ký tự (OQ-P6). Chạy service install --binary với đường dẫn do kẻ khác kiểm soát là chạy mã tùy ý bằng tài khoản dịch vụ, nhưng người gọi đã là root nên ranh giới tin cậy không đổi.
  • Chạy enroll bằng root (OQ-P2) hay bản thân người vận hành root có thể vô hiệu hóa cách ly của tài khoản dịch vụ, nhưng không mở rộng quyền cho agent.

11.2. Đường ống phân quyền năm bước ​

BướcAi làmGhi chú
1. Xác thực người thao tácHệ điều hànhEuid bằng 0 cho svc.Manager và install.sh (trừ --dry-run)
2. Xác thực nguồn phát hànhinstall.shChữ ký của SHA256SUMS (khóa công khai của người vận hành)
3. Xác thực nội dunginstall.shChecksum từng gói so với dòng trong SHA256SUMS, tên gói từ danh sách đã xác minh
4. Xác thực đầu vào cấu hìnhpostinstall.shDanh sách trắng ký tự, https://
5. Giam tiến trìnhsystemd (unit)Tài khoản không đặc quyền, không capability

11.3. Điểm neo zero-trust ​

Điểm neoÝ nghĩa
Không tin thư mục phát hànhTên gói và checksum lấy từ SHA256SUMS đã có chữ ký, không từ danh sách thư mục
Không tin đầu vào của người càiMọi giá trị đi vào YAML, tên gói, phiên bản đều qua danh sách trắng
Không bao giờ bỏ qua checksum--allow-unsigned chỉ bỏ chữ ký, không bỏ checksum
Không khởi động khi chưa enrollservice install không start, postinstall chỉ enable --now sau enroll thành công hoặc khi đã có danh tính
Không tin tệp chạyTiến trình không tự nâng quyền (NoNewPrivileges, không capability)
Không cổng mởRestrictAddressFamilies cho phép socket nhưng agent chỉ là client, không có tham số để lắng nghe

12. Cấu hình & Tinh chỉnh ​

12.1. Tunables ​

Thành phần không có tệp cấu hình riêng. Các núm chỉnh nằm ở bốn nơi: chỉ thị trong unit (chỉ sửa được bằng drop-in của systemd hoặc sửa nguồn), biến môi trường của postinstall.sh, cờ của install.sh, biến của package.sh và make. Khóa của agent.yaml thuộc L3 Enroll mục 12.1.

Chỉ thị unit đáng chỉnh

KhóaMặc định (dải hợp lệ)Ý nghĩaNạp nóngNguồn ghi đè
MemoryMax96M (theo systemd)Trần cứng cgroup, vượt là bị giếtKhông (daemon-reload rồi restart)Drop-in systemctl edit
CPUQuota25%Trần CPUNhư trênDrop-in
TasksMax128Trần luồng và tiến trìnhNhư trênDrop-in
LimitNOFILE1024Trần mô tả tệpNhư trênDrop-in
Restart, RestartSecon-failure, 5 sChính sách chạy lạiNhư trênDrop-in
RestartPreventExitStatus2 3 4 5Mã thoát không chạy lạiNhư trênDrop-in
StartLimitIntervalSec, StartLimitBurst300 s, 10Hạn mức chạy lạiNhư trênDrop-in
TimeoutStopSec30 sThời gian dừng êm trước SIGKILLNhư trênDrop-in
ReadWritePaths/var/lib/accesshub-agent /var/log/accesshub-agentĐường ghi được duy nhất (kèm StateDirectory, LogsDirectory)Như trênDrop-in. Phải thêm khi đổi state_dir hoặc log.file (OQ-P5)
ExecStart/usr/bin/accesshub-agent runTệp chạyNhư trênservice install --binary (viết lại), hoặc drop-in

Drop-in (/etc/systemd/system/accesshub-agent.service.d/*.conf) được systemd hỗ trợ nhưng thành phần này không tạo, không quản lý và không có kiểm thử. Sửa tay tệp unit của gói sẽ bị ghi đè khi nâng cấp (deb không coi unit là conffile do nfpm khai báo, suy luận từ nfpm.yaml).

Biến của postinstall.sh và cờ của install.sh: xem bảng ở 5.1 và 5.2 (ACCESSHUB_COLLECTOR_URL, ACCESSHUB_LICENSE, ACCESSHUB_LICENSE_FILE, ACCESSHUB_PROXY_URL, ACCESSHUB_NO_START, --version, --base-url, --pubkey, --allow-unsigned, --proxy, --no-start, --dry-run). Mọi biến đều không có nạp nóng: chỉ đọc một lần lúc cài.

Tham số CLI của thành phần

Tham sốMặc địnhÝ nghĩa
service install --binary PATHtệp chạy hiện tại (đã giải symlink)Đường dẫn tuyệt đối ghi vào ExecStart
service install --enabletắtChạy thêm systemctl enable (không bao giờ start)
uninstall --purgetắtXóa state, log, cấu hình và tài khoản
service start, stop, restartkhông cóGọi systemctl tương ứng

Tham số dựng phát hành

BiếnMặc địnhÝ nghĩa
VERSIONgit describe --tags --always --dirty, hoặc devPhiên bản nhúng vào tệp chạy và suy ra phiên bản gói (7.4.5)
COMMIT, DATEtừ git, từ ngày giờ UTCNhúng qua -ldflags
NFPMnfpmĐường dẫn công cụ đóng gói
OUTdist/release (dist/snapshot cho make snapshot)Thư mục đầu ra, bị xóa rồi tạo lại khi dựng
SIGN_HOOKrỗngLệnh ký SHA256SUMS, nhận đường dẫn tệp làm đối số, phải tạo SHA256SUMS.sig khác rỗng
MAX_BYTES20971520 (20 MiB)Trần kích thước tệp chạy của cross-build.sh

Hằng số không cấu hình được

HằngGiá trịVai trò
Tên tài khoản và nhómaccesshub-agentCứng trong unit, script, svc.Manager
Thư mục/etc/accesshub-agent, /var/lib/accesshub-agent, /var/log/accesshub-agentCứng trong NewManager, script và unit
QuyềnState và log 0750, unit 0644, agent.yaml 0640 root:accesshub-agentCứng trong script, svc, nfpm.yaml (OQ-P1)
Danh sách trắng ký tự giá trị YAMLA-Za-z0-9._~:/?#@%+=&,-valid_value trong postinstall.sh
Danh sách trắng tên gói và phiên bảnA-Za-z0-9._+~-install.sh
Gốc tải mặc địnhhttps://downloads.example.com/agentĐịa chỉ giữ chỗ (OQ-P10, OQ-P11)

12.2. Feature flags ​

Không có cờ tính năng. Hai tùy chọn opt-in mang tính đánh đổi an toàn: --allow-unsigned (bỏ kiểm chữ ký, vẫn kiểm checksum, in cảnh báo) và --dry-run (không đổi gì). ACCESSHUB_NO_START hoạt động như cờ triển khai, không phải cờ tính năng.


13. Telemetry & Vận hành ​

13.1. Metrics ​

Thành phần này không phát chỉ số nào: nó chỉ chạy lúc cài, gỡ và dựng. Số liệu liên quan tới dịch vụ đang chạy nằm ở L3 Collectors và L3 WAL và Sender, và cgroup của systemd (systemctl status, systemd-cgtop) cho biết bộ nhớ và CPU thực. Khoảng trống (ĐỀ XUẤT): chưa có chỉ số hay cảnh báo cho "số lần systemd chạy lại agent" hay "số máy cài chưa enroll" (OQ-P19).

13.2. Log schema ​

Không có slog ở thành phần này. Thông điệp nằm ở ba chỗ:

Sự kiện (msg)MứcTrường thêmKhi nào
warning: ... (script gói)Cảnh báo (stderr, tiền tố warning:)Tự doEnroll lỗi, giá trị bị bỏ qua, không đọc được tệp token, systemctl enable --now lỗi
install.sh: ...Thông tin hoặc lỗi (stderr), lỗi qua dieTự doMỗi bước tải, xác minh, cài. Lỗi kết thúc bằng thoát 1
service installed, next: enroll the agent ...Thông tin (stdout)Đường dẫn tệp chạy, lệnh enroll, lệnh enable --nowservice install thành công
warning: ... is not loaded hoặc tương tựCảnh báo (stderr)Lỗi systemctlUninstall gặp disable --now hoặc daemon-reload lỗi
Nhật ký dịch vụ đang chạyTheo log.levelTheo L3 Enroll mục 13.2Vào journald vì stderr của unit

Các chuỗi này là cho người đọc, chưa phải hợp đồng ổn định cho script (xem OQ-E9 ở L3 Enroll).

13.3. Alert to runbook ​

Thành phần không tự cảnh báo (ĐỀ XUẤT: OnFailure= hoặc kiểm tra bên ngoài, OQ-P19).

Điều kiệnRunbook
Dịch vụ failed sau service install thủ công, journalctl báo thiếu collector_url (mã 3)Ghi collector_url vào agent.yaml (hoặc cài lại trên máy mới với --collector URL), enroll bằng tài khoản dịch vụ, systemctl restart (OQ-P3)
Dịch vụ failed với mã 4Chạy sudo -u accesshub-agent accesshub-agent enroll --token-file <file> (L3 Enroll)
Dịch vụ failed với mã 5Token sai hoặc đã dùng: xin token mới (L3 Enroll mục 13.3)
Dịch vụ failed mã 1 lặp lại rồi start limit hitXem journalctl -u accesshub-agent. Nếu do quyền credentials.json: chown accesshub-agent:accesshub-agent và chmod 600 (OQ-P2). Sau khi sửa: systemctl reset-failed rồi restart
Dịch vụ bị giết, journalctl có oom-kill hoặc Memory cgroupGiảm limits.memory_limit hoặc nâng MemoryMax bằng drop-in (OQ-P4)
install.sh in SIGNATURE VERIFICATION FAILEDDừng. Kiểm khóa công khai và nguồn tải, không dùng --allow-unsigned để lách
install.sh in CHECKSUM MISMATCHDừng. Tải lại, so với kênh phát hành khác, báo đội phát hành
Gói cài xong, cảnh báo enroll failedSửa nguyên nhân (mạng, token), chạy lại enroll bằng tài khoản dịch vụ rồi systemctl enable --now
Gỡ rpm còn dữ liệuaccesshub-agent uninstall --purge trước khi gỡ gói (OQ-P8)
uninstall --purge đã chạy sau cài góiCài lại gói, enroll lại (OQ-P13)

13.4. Probes ​

Không có endpoint. Quan sát cục bộ:

KênhNội dung
systemctl is-active, is-enabled, status accesshub-agentTrạng thái unit, mã thoát gần nhất, số lần chạy lại
journalctl -u accesshub-agentNhật ký của dịch vụ và lý do thoát
accesshub-agent check-configKiểm agent.yaml, không gọi mạng (L3 Enroll mục 13.4)
accesshub-agent collect-onceThu một lần, kiểm bộ thu, không cần danh tính
systemd-analyze verify accesshub-agent.serviceKiểm cú pháp unit (đã chạy thủ công một lần, systemd 255, chỉ phàn nàn thiếu tệp chạy)
systemd-analyze security accesshub-agent.serviceChấm điểm hardening. Chưa chạy, ĐỀ XUẤT
dpkg -L, dpkg-deb -c (deb), rpm -qlp (rpm)Kiểm nội dung gói. Chỉ dpkg-deb đã chạy thủ công (mục 14)
Mã thoát của install.sh, package.sh0 hoặc 1

13.5. Trace propagation ​

Không áp dụng. Thành phần không có lời gọi mạng riêng ngoài curl của install.sh, không gắn X-Request-Id.


14. Kế hoạch kiểm thử ​

Loại Test & Phạm viÁnh xạ mục tiêuMục tiêu kỹ thuậtVí dụ kịch bản (Test ID)
Unit: unit và hardeningAC-P01, AC-P02, NFR-P01, NFR-P12Unit đóng gói có đủ chỉ thị bắt buộc, RenderUnit chỉ đổi ExecStartTestPackagedUnitCarriesRequiredHardening, TestRenderUnitRewritesOnlyTheBinary
Unit: svc.ManagerAC-P03 đến AC-P09Cài, gỡ, điều khiển với Run, LookPath, Lookup, Chown, Euid giảTestInstallCreatesAccountDirsUnitAndReloads, TestInstallKeepsExistingAccountAndSkipsEnableByDefault, TestInstallRequiresRootAndAbsoluteBinary, TestInstallFailsClearlyWithoutUseradd, TestUninstallKeepsDataUnlessPurge, TestUninstallToleratesServiceThatIsNotLoaded, TestControlValidatesActionAndRoot
CLI: lệnh serviceAC-P10 đến AC-P12Đường dẫn tệp chạy, cờ, thông điệp, Linux-onlyTestServiceInstallWritesUnitForThisExecutable, TestServiceInstallHonorsBinaryFlagAndRejectsRelative, TestServiceControlAndUninstall, TestServiceNeedsRootAndAKnownAction, TestServiceIsLinuxOnlyForNow
Tĩnh: script và nfpmAC-P13, AC-P14Cú pháp, quyền thực thi, shellcheck (bỏ qua nếu không có công cụ), mọi src tồn tại, agent.yaml mẫu hợp lệTestScriptsParseAndAreExecutable, TestShellcheckClean, TestNfpmSourcesExist, TestSampleConfigIsValidWithCollectorOverride
Hành vi: postinstall.shAC-P15 đến AC-P23, NFR-P08 đến NFR-P10Chạy script thật trong thư mục giả với systemctl, runuser, useradd, tệp chạy giả ghi lại lệnhTestPostinstallWithoutEnvOnlyPreparesDirectories, TestPostinstallEnrollsThroughStdinAndStarts, TestPostinstallReplacesExistingCollectorURLOnce, TestPostinstallTokenFileIsRemovedAfterEnroll, TestPostinstallKeepsExistingCredentials, TestPostinstallEnrollFailureDoesNotFailPackageOrStart, TestPostinstallNoStartOnlyEnables, TestPostinstallRejectsUnsafeValues, TestPostinstallNeedsBothURLAndToken
Hành vi: preremove.sh, postremove.shAC-P24, NFR-P09Đối số deb và rpm, chỉ purge mới xóaTestPreremoveOnlyStopsOnRealRemoval, TestPostremoveKeepsDataUnlessPurge
Hành vi: install.shAC-P25 đến AC-P27, NFR-P07Từ chối không khóa, --allow-unsigned vẫn kiểm checksum, chữ ký, đầu vào xấuTestInstallRefusesWithoutKeyOrOptOut, TestInstallAllowUnsignedStillChecksums, TestInstallVerifiesSignature, TestInstallRejectsUnsafeInput
CI: trần kích thướcNFR-P05, FR-P14Dựng chéo bốn mục tiêu, kiểm MAX_BYTESJob cross-build (chạy scripts/cross-build.sh, không phải kiểm thử Go)
Chưa có: cài gói thậtNFR-P06, FR-P15Cài .deb và .rpm thật trên distro mục tiêu, kiểm systemd chạy unitĐỀ XUẤT: ma trận distro trong container hoặc VM (OQ-P12, D-13, R-04)
Chưa có: kiểm nội dung rpmFR-P07rpm -qlp, rpm -qp --scriptsĐỀ XUẤT (OQ-P12). Mới kiểm .deb bằng dpkg-deb một lần thủ công
Chưa có: nhánh su và đường rpm của install.shFR-P09, FR-P11Dự phòng khi không có runuser, dnf, yum, rpm -UĐỀ XUẤT (OQ-P12)
Chưa có: preinstall.shFR-P08Hành vi tạo tài khoản và thoát 1, hiện chỉ có kiểm cú pháp và shellcheckĐỀ XUẤT (OQ-P12)
Chưa có: package.sh, quy tắc phiên bảnFR-P12, FR-P13Bảng ca cho v1.2.3, 9d76488, -dirty, ký tự lạ, SIGN_HOOK lỗiĐỀ XUẤT (OQ-P12)
Chưa có: hành vi systemdNFR-P04, NFR-P11Chạy lại, dừng theo mã, start limit hit, dừng êm trong 30 sĐỀ XUẤT: kiểm thử trong container có systemd (OQ-P12)
Chưa có: systemd-analyze securityNFR-P01, NFR-P02Ngưỡng điểm hardening trong CIĐỀ XUẤT (OQ-P12)
Chưa có: bẫy cài thủ côngFR-P04service install ghi mẫu, nhắc collector_url, nhận --collector; start khi thiếu collector_url vẫn failed (mã 3)ĐÃ HIỆN THỰC (OQ-P3), chưa có kiểm thử hành vi trên systemd thật
Chưa có: WindowsFR-P17Dịch vụ Windows, MSITHIẾT KẾ, CHƯA XÂY (D-05, AGT-7)

Lưu ý khi chạy: TestShellcheckClean bỏ qua khi máy không có shellcheck, nên CI không có công cụ này thì kết quả xanh không chứng minh script sạch. Các kiểm thử script gói dùng sh và tệp giả nên chỉ chạy trên Linux và macOS, không chạy trên Windows. Hai kiểm tra thủ công một lần (không lặp lại được từ kho mã và không tính là kiểm thử): systemd-analyze verify trên unit (systemd 255) và dựng thật gói deb và rpm bằng nfpm (chỉ kiểm deb bằng dpkg-deb). Cả hai dùng tệp tạm đã được xóa.


15. Trình tự triển khai ​

15.1. Ma trận milestone ​

MilestoneNội dungPhụ thuộcĐóng góp nghiệm thu
P1internal/svc (Manager, RenderUnit) và lệnh service, uninstall. ĐÃ HIỆN THỰCKhôngAC-P02 đến AC-P12
P2Unit một nguồn, hardening, hạn mức chạy lại. ĐÃ HIỆN THỰCKhôngAC-P01
P3nfpm.yaml và bốn script gói. ĐÃ HIỆN THỰC (trong cây làm việc, AGT-6 chưa commit, D-13)P1, P2AC-P13 đến AC-P24
P4install.sh xác minh chữ ký và checksum. ĐÃ HIỆN THỰC (chưa commit)P3AC-P25 đến AC-P27
P5package.sh, make package, snapshot, checksums, cross-build.sh. ĐÃ HIỆN THỰC (chưa commit, riêng cross-build đã có job CI)P3, P4NFR-P05
P6Commit AGT-6, ma trận distro, kiểm .rpm, kiểm thử nhánh còn thiếu (OQ-P12). ĐỀ XUẤTP3, P4, P5AC mới (chưa có)
P7Job CI đóng gói, chạy package.sh, shellcheck và kiểm nội dung gói. ĐỀ XUẤT (D-12)P6AC mới (chưa có)
P8Kho gói, khóa ký, latest, SBOM, địa chỉ thật thay giữ chỗ. THIẾT KẾ, CHƯA XÂY (AGT-11, Q2, Q3, OQ-P11)P7FR-P16
P9Khép các bẫy: agent.yaml 0640 (OQ-P1, ĐÃ XONG), service install thông báo và ghi khóa thiếu (OQ-P3, ĐÃ XONG), cảnh báo root enroll (OQ-P2), /var/log trong gói (OQ-P7), purge cho rpm (OQ-P8), thoát ký tự RenderUnit (OQ-P6). MỘT PHẦN (OQ-P1, OQ-P3 xong, còn lại ĐỀ XUẤT)P6AC mới (chưa có cho phần còn lại)
P10Dịch vụ Windows, MSI, install.ps1. THIẾT KẾ, CHƯA XÂY (AGT-7, D-05, OQ-P9)P1, Enroll E9FR-P17

15.2. Sơ đồ phụ thuộc milestone ​

mermaid
flowchart LR
  P1["P1 · svc và lệnh service"]
  P2["P2 · Unit và hardening"]
  P3["P3 · nfpm và script"]
  P4["P4 · install.sh"]
  P5["P5 · package.sh và make"]
  P6["P6 · Commit và ma trận distro"]
  P7["P7 · Job CI đóng gói"]
  P8["P8 · Kho và ký"]
  P9["P9 · Khép các bẫy"]
  P10["P10 · Windows"]
  P1 --> P3
  P2 --> P3
  P3 --> P4
  P3 --> P5
  P4 --> P5
  P5 --> P6
  P6 --> P7
  P7 --> P8
  P6 --> P9
  P1 --> P10
  style P1 fill:#2d4a3e,stroke:#5fb37a,color:#fff
  style P2 fill:#2d4a3e,stroke:#5fb37a,color:#fff
  style P3 fill:#2d4a3e,stroke:#5fb37a,color:#fff
  style P4 fill:#2d4a3e,stroke:#5fb37a,color:#fff
  style P5 fill:#2d4a3e,stroke:#5fb37a,color:#fff
  style P6 fill:#3a3320,stroke:#d9b84a,color:#fff
  style P7 fill:#3a3320,stroke:#d9b84a,color:#fff
  style P9 fill:#3a3320,stroke:#d9b84a,color:#fff
  style P8 fill:#444,stroke:#aaa,color:#fff
  style P10 fill:#444,stroke:#aaa,color:#fff

Chú giải: xanh lá là đã hiện thực (P3 đến P5 còn nằm ngoài lịch sử git), vàng là đề xuất, xám là thiết kế chưa xây. Đường găng tới kho và ký là P3, P5, P6, P7, P8. P9 độc lập với P7 và P8 nên có thể làm song song ngay sau P6. P10 còn cần phía Enroll (bảo vệ token trên Windows).


Phụ lục A: Open Questions ​

#Câu hỏiHành vi tạm thờiOwnerMã theo dõi
OQ-P1agent.yaml được gói cài 0644 root:root nên ai cũng đọc được, mà có thể chứa proxy_url kèm mật khẩu (trả lời OQ-E19). Có đặt 0640 và nhóm accesshub-agent không? ĐÃ XỬ LÝ: gói, service install và set_key đều 0640 root:accesshub-agent0640 root:accesshub-agent (đã làm)đã đóngL3-PKG-OQ1
OQ-P2enroll bằng root (tay) tạo credentials.json thuộc root mà dịch vụ không đọc được, rồi run thoát mã 1 và bị chạy lại tới hết hạn mức (OQ-E5). Có cảnh báo khi root, hoặc tự chown?Hướng dẫn và postinstall dùng tài khoản dịch vụchưa chỉ địnhL3-PKG-OQ2
OQ-P3service install không ghi agent.yaml nên run thoát mã 3 và, vì mã 3 nằm trong RestartPreventExitStatus, dịch vụ nằm failed. Thông điệp không nhắc collector_url. Có in nhắc, hoặc nhận --collector? ĐÃ XỬ LÝ: ghi agent.yaml mẫu khi chưa có, nhận --collector, nhắc collector_urlĐã làmđã đóngL3-PKG-OQ3
OQ-P4MemoryMax=96M (cứng) so với limits.memory_limit mặc định 64 MiB và cho phép tới 4 GiB: đặt lớn hơn 96 MiB thì bị OOM kill thay vì tự nén. Nên kiểm khi nạp cấu hình hay nâng MemoryMax?Cố định 96Mchưa chỉ địnhL3-PKG-OQ4
OQ-P5ReadWritePaths cố định hai thư mục, nên state_dir hoặc log.file tùy chỉnh ngoài đó bị ProtectSystem=strict chặn ghi. Có sinh drop-in hoặc kiểm đường dẫn khi cài?Người vận hành tự thêm ReadWritePathschưa chỉ địnhL3-PKG-OQ5
OQ-P6RenderUnit không thoát ký tự: đường dẫn có khoảng trắng hoặc % làm hỏng dòng ExecStart. Có thoát hoặc từ chối?Chỉ kiểm tuyệt đốichưa chỉ địnhL3-PKG-OQ6
OQ-P7nfpm không khai báo /var/log/accesshub-agent, và gỡ thường cố ý để lại tài khoản. Có khai báo thư mục và có xóa tài khoản khi gỡ?Thư mục do unit và script tạo, tài khoản giữchưa chỉ địnhL3-PKG-OQ7
OQ-P8rpm không có bước purge: gỡ bằng rpm -e hoặc dnf remove để lại dữ liệu và tài khoản mãi mãi. Cách gỡ sạch chuẩn là gì (vì uninstall --purge phải chạy trước)?Dùng uninstall --purge trước khi gỡ góichưa chỉ địnhL3-PKG-OQ8
OQ-P9Thông báo Windows của service nêu AGT-8 nhưng L2 gán dịch vụ Windows cho AGT-7 (cùng OQ-E16). Sửa thông báo hay L2? ĐÃ XỬ LÝ: thông báo nay nêu AGT-7Đã sửa thông báođã đóngL3-PKG-OQ9
OQ-P10Giá trị mặc định của --base-url là địa chỉ giữ chỗ, và install.sh chạy qua curl | sh thì chính nó chưa được xác minh. Hướng dẫn chuẩn là gì: tải, kiểm chữ ký rồi mới chạy?Bắt buộc truyền --base-url trên thực tếchưa chỉ địnhL3-PKG-OQ10
OQ-P11Chưa có kho gói, khóa ký, job CI đóng gói, SBOM, và maintainer trong nfpm.yaml là email giữ chỗ (D-12, R-03, Q2, Q3). Ai cấp khóa, địa chỉ phát hành và danh tính bảo trì?Phát hành dạng tệp, người vận hành tự cấp khóachưa chỉ địnhL3-PKG-OQ11
OQ-P12Chưa có kiểm thử cài gói thật, ma trận distro, kiểm .rpm, nhánh su và rpm của install.sh, hành vi preinstall.sh, package.sh, hành vi systemd, systemd-analyze security (D-13, R-04, mục 14). Khi nào và ở đâu chạy?Chỉ kiểm tĩnh và hành vi script bằng tệp giảchưa chỉ địnhL3-PKG-OQ12
OQ-P13Hai bản unit (gói ở /lib hoặc /usr/lib, service install ở /etc/systemd/system thắng), uninstall chỉ xóa bản /etc, và uninstall --purge sau cài gói xóa /etc/accesshub-agent của gói trong khi gói còn. Có phát hiện gói đã cài và từ chối hoặc đổi hành vi?Không phát hiệnchưa chỉ địnhL3-PKG-OQ13
OQ-P14Gói tar.gz không có script gói: phải tự service install, viết agent.yaml, enroll. Có cần script cài riêng hay ghi rõ hơn trong hướng dẫn?Hướng dẫn thủ côngchưa chỉ địnhL3-PKG-OQ14
OQ-P15Nhánh "already enrolled" của postinstall không xóa tệp token, nên tệp token còn lại trên đĩa dù đã vô dụng. Có xóa?Giữ tệpchưa chỉ địnhL3-PKG-OQ15
OQ-P16Gỡ thường rồi cài lại không biến môi trường giữ danh tính nhưng không bật lại dịch vụ (vì preremove đã disable). Có chủ đích không, và có cần enable --now khi đã có danh tính?Phải systemctl enable --now taychưa chỉ địnhL3-PKG-OQ16
OQ-P17--proxy URL của install.sh đi qua argv nên mật khẩu proxy lộ trong danh sách tiến trình. Có nhận qua biến môi trường hoặc tệp?Chấp nhận, ghi chú trong tài liệuchưa chỉ địnhL3-PKG-OQ17
OQ-P18Token trong ACCESSHUB_LICENSE sống suốt quá trình cài và đọc được qua /proc/<pid>/environ. Có ưu tiên tệp token trong hướng dẫn và cảnh báo khi dùng biến môi trường?Đưa vào ống ở postinstall, biến vẫn tồn tại ở tiến trình chachưa chỉ địnhL3-PKG-OQ18
OQ-P19Không có kiểm tra sức khỏe sau nâng cấp, tự quay lại, OnFailure= hay chỉ số cho "đã cài nhưng chưa enroll" và "chạy lại nhiều lần". Có thêm?Phát hiện bằng systemctl status thủ côngchưa chỉ địnhL3-PKG-OQ19

Phụ lục B: ADR nội bộ ​

Mã ADRQuyết địnhTrạng tháiĐộng lực
ADR-P01Một tệp unit duy nhất, nhúng vào tệp chạy và nfpm lấy cùng nguồn, RenderUnit chỉ viết lại ExecStartĐã hiện thựcHardening có hiệu lực như nhau ở hai đường cài. Đánh đổi: không thoát ký tự (OQ-P6), ReadWritePaths cố định (OQ-P5)
ADR-P02service install và postinstall không bao giờ khởi động dịch vụ trước khi có danh tínhĐã hiện thựcTránh vòng chạy lại vô ích khi chưa có collector_url hay credentials.json. Đánh đổi: dịch vụ failed nếu người vận hành quên collector_url (OQ-P3, đã có nhắc và --collector)
ADR-P03Enroll trong postinstall bằng tài khoản dịch vụ, token qua ống, và không bao giờ làm hỏng góiĐã hiện thựcCài hàng loạt không tương tác, credentials.json đúng chủ, lỗi mạng không để máy cài dở (ADR-E09). Đánh đổi: pipeline phải tự kiểm enroll (OQ-P18, OQ-P19)
ADR-P04install.sh xác minh trước khi tin: chữ ký rồi tên gói từ SHA256SUMS rồi checksum, không bao giờ bỏ checksumĐã hiện thựcKẻ chiếm kho không thay được gói. Đánh đổi: phụ thuộc kênh phân phối khóa (OQ-P10, OQ-P11)
ADR-P05agent.yaml là config|noreplace, nâng cấp không ghi đèĐã hiện thựcGiữ chỉnh sửa của người vận hành. Đánh đổi: khóa mới trong mẫu không tự xuất hiện (cùng OQ-E13)
ADR-P06Gỡ thường giữ dữ liệu và tài khoản, chỉ purge mới xóaĐã hiện thựcCài lại và nâng cấp không mất danh tính. Đánh đổi: rpm không có purge (OQ-P8), tài khoản mồ côi (OQ-P7)
ADR-P07Một cấu hình nfpm cho cả deb và rpm, package.sh thay AGENT_BINARY bằng sedĐã hiện thựcMột nguồn cho hai định dạng. Đánh đổi: nfpm không mở rộng biến trong contents.src, phải thay trước
ADR-P08Ký bằng hook ngoài (SIGN_HOOK) thay vì nhúng công cụ ký vào package.shĐã hiện thựcKhóa ký không nằm trong kho mã. Đánh đổi: chưa có hook thực, chưa có CI (OQ-P11)
ADR-P09Hạn mức chạy lại hữu hạn, mã 2 đến 5 dừng hẳnĐã hiện thựcKhông đốt CPU với lỗi tự không khỏi. Đánh đổi: mã 1 gộp nhiều nguyên nhân, không có cảnh báo khi failed (OQ-P19)

Phụ lục C: Section Profile ​

Phân mụcHồ sơ quy chuẩnTrạng thái điềnGiải trình
§0 Metadata & Sign-offBắt buộcĐã điềnNgười ký để "chưa chỉ định"
§1 ScopeBắt buộcĐã điền
§2 Yêu cầuBắt buộcĐã điềnFR-P01 đến P17, NFR-P01 đến P12, AC-P01 đến P27, QAS-P01 đến P06
§3 Kiến trúcBắt buộcĐã điền
§4 Domain modelBắt buộcĐã điềnHai vùng: dịch vụ và phát hành
§5 API contractBắt buộcĐiền thu gọnKhông có API phục vụ. Hợp đồng gồm CLI, cờ bộ cài, biến môi trường, bộ phát hành
§6 Data schemaTùy chọnĐiền thu gọnKhông có CSDL. Ánh xạ tệp, quyền và chủ sở hữu thay cho lược đồ
§7 Thuật toánBắt buộcĐã điền9 luồng, hai máy trạng thái, bảy thuật toán
§8 Xử lý lỗiBắt buộcĐã điền
§9 Suy thoáiBắt buộcĐã điền9.2: không có dữ liệu riêng, khôi phục bằng cài lại
§10 Đồng thờiBắt buộcĐiền thu gọnKhông có giao dịch CSDL, ranh giới là thao tác tệp và khóa của trình quản lý gói
§11 Bảo mậtBắt buộcĐã điềnNêu thẳng các điểm yếu còn lại (R-03)
§12 Cấu hìnhBắt buộcĐã điềnKhông có feature flag
§13 TelemetryBắt buộcĐiền thu gọnKhông phát chỉ số, không probe mạng, không trace
§14 Kiểm thửBắt buộcĐã điềnCó 9 khoảng trống đề xuất hoặc chưa xây
§15 Triển khaiBổ sungĐã điền
Trang này có giúp được bạn không?
Sửa trang này

Nội dung đồng bộ từ kho mã access-hub-agent lúc 15:42, 03/10/2026. Khi tài liệu và mã khác nhau, mã thắng.