Access Hub Scanner
Đang phát triểnĐồng bộ từ mã nguồn lúc 10:57, 03/10/2026
Skip to content

Tích hợp với Access Hub ​

Đây là đặc tả phần việc trong Access Hub (Laravel) cho trưởng nhóm Access Hub, theo cùng cách repo Access Hub Collector đặc tả HUB-1 đến HUB-18 (access-hub-collector/docs/06-access-hub-integration.md). Repo này không sửa Access Hub. Tên bảng, quyền, đường dẫn là đề xuất, chốt khi làm HUB-SEC-1.

26 phút đọcCập nhật 03/10/2026access-hub-scanner, docs/08-hub-integration.md

1. Nguyên tắc ​

  1. Access Hub là nguồn sự thật cho vòng đời finding (trạng thái, ngoại lệ, SLA, người phụ trách), cài đặt, quyền, thông báo. Secmatch giữ inventory và kết quả so khớp thô (ADR 0008).
  2. Mọi model theo tenant dùng CompanyScope, uuid làm khóa công khai, Auditable khi có thao tác người dùng, theo quy ước Server, MonitoringAgent.
  3. Không mã hóa finding, gói, kết quả kiểm tra: chúng phải tìm kiếm, lọc được. Chỉ bí mật (token dịch vụ của secmatch nếu lưu trong DB, bí mật webhook đã có) đi qua CompanyCrypto (ENC-2, nhánh feat/biz-0).
  4. Một công ty đang hoạt động tại một thời điểm, không có danh sách chéo công ty. Công ty mẹ chỉ xem công ty con khi được cấp quyền theo cơ chế hiện có.
  5. Nhân viên nền tảng không có đường đọc dữ liệu quét của khách hàng (không màn hình, không phiên truy cập); chỉ có thống kê ẩn danh (mục 8).
  6. Gọi secmatch qua một client có timeout ngắn, thử lại, ngắt mạch, giống MonitoringCollectorClient (app/Services/Monitoring/Collector/MonitoringCollectorClient.php). Secmatch không sẵn sàng thì giao diện hiện "Không có dữ liệu", không lỗi 500.

2. Bảng dữ liệu (MySQL của Access Hub) ​

BảngCột chínhGhi chú
security_settingscompany_id unique, enabled, inventory_interval_hours, checks_interval_hours, checks_enabled, disabled_checks json, walk_exclude json, thresholds json, sla_days json, severity_overrides json, internet_facing_tag, db_stale_days, content json, fp_company_key_encrypted, fp_company_key_versionTheo công ty. Giá trị bị kẹp theo gói (mục 6). content là cấu hình quét nội dung (07 mục 8); fp_company_key_encrypted là K_company mã hóa bằng CompanyCrypto (ENC-2), không bao giờ trả ra API hay giao diện
security_findingsid uuid, company_id, server_id, finding_key, kind, vuln_id, aliases json, advisory_ids json, ecosystem, package_key, packages json, installed_version, fixed_version, fix_status, fix_channel, minor, kernel, check_id, check_subject, detector_id, detector_version, file_path, file_line, file_column, match_count, preview, fingerprint, confidence, exposure, file_modified_at, severity_label, cvss_score, cvss_vector, score_source, epss, epss_percentile, kev, kev_due_date, f_exposure, f_env, risk, priority, status, exception_id, first_seen_at, last_seen_at, fix_available_at, sla_due_at, sla_paused_seconds, resolved_at, resolved_reason, reboot_required, last_event_seq, db_versionCompanyScope. kind gồm vulnerability, check, secret, sensitive_data. Unique (company_id, finding_key). Chỉ mục (company_id, status, priority), (company_id, server_id, status), (company_id, vuln_id), (company_id, package_key), (company_id, sla_due_at), (company_id, kind, status), (company_id, fingerprint). Cột nội dung chỉ chứa các trường ADR 0011, không có cột giá trị
security_finding_eventsid, company_id, finding_id, event_id unique, seq, type, occurred_at, payload jsonNhật ký, khử trùng theo event_id, dọn theo security_history_days
security_exceptionsid uuid, company_id, type, scope_kind, server_id, tag, vuln_id, package_key, check_id, reason, ticket_ref, requested_by, approved_by, self_approved, status, decided_at, expires_at, revoked_at, revoked_byCompanyScope, Auditable
security_server_scanscompany_id, server_id unique, last_event_seq, last_scanned_at, scanner_version, db_version, os_id, os_version, os_codename, match_status, release_support, kernel_running, livepatch_active, open_findings, package_count, walk_truncated, error_codes json, listening json, reboot_required, server_risk, open_p1, open_p2, open_p3, open_p4, content_stats json, content_baseline_complete, open_secrets_high, pii_filesMột dòng mỗi máy, phục vụ dashboard và tab máy chủ
scan_hostsid, uuid, company_id, server_id nullable, host_id unique, public_key, prev_public_key nullable, prev_key_expires_at nullable, machine_id_hash, hostname, os_id, os_version, uploader_version, state, version, scan_requested_at nullable, enrolled_at, last_seen_at, revoked_at, revoked_by, revoked_reasonMáy Scanner (ADR 0001): danh tính của gói Scanner trên một máy, độc lập với monitoring_agents. CompanyScope, Auditable. state: active, revoked. Đếm vào hạn mức scan_hosts. Unique (company_id, machine_id_hash) cho máy chưa thu hồi. server_id gắn với Server chung, nên máy cài cả giám sát và Scanner có cả MonitoringAgent và scan_hosts trỏ cùng một Server
scan_enrolment_codesid uuid, company_id, server_id nullable, token_hash, expires_at, used_at, used_by_host_id, created_by, revoked_atMã enroll một lần dùng, băm SHA-256, chỉ hiện bản rõ một lần lúc tạo, hết hạn 24 giờ. CompanyScope, Auditable
security_check_statescompany_id, server_id, check_id, subject, check_version, status, evidence json, observed_atUnique (server_id, check_id, subject)
security_expected_portsid uuid, company_id, scope json, proto, port_from, port_to, bind_scope, note, created_byCompanyScope, Auditable. scope giải theo máy, tag, vai trò, môi trường như MonitoringRuleScopeResolver
security_stats_dailycompany_id, date, open_by_priority json, opened, resolved, overdue, accepted, false_positive, kev_open, servers_scanned, servers_stale, mttr_seconds_by_priority json, sla_compliance, checks_pass_rate jsonUnique (company_id, date)
security_vulnerabilitiesvuln_id unique, summary, published_at, modified_at, cvss json, cwe json, references json, kev, epss, epss_percentile, updated_atToàn cục (dữ liệu tham chiếu công khai, không thuộc công ty). Không có endpoint liệt kê cho tenant: tenant chỉ đọc qua join với finding của chính mình, để không lộ "có công ty nào đó dính CVE X"
platform_security_stats_dailydate unique, metrics jsonKhông có company_id. Chỉ số tổng hợp ẩn danh (mục 8)

Gói, dịch vụ, phần mềm ngoài gói, thống kê tệp và tệp đáng chú ý theo máy không lưu trong MySQL của Access Hub (Q4): tra qua secmatch (07 mục 7). Finding nội dung lưu trong security_findings vì có vòng đời.

Ghi theo lô: security_findings nhận lô sự kiện đến 200 mục, cập nhật bằng upsert theo (company_id, finding_key) trong một giao dịch mỗi lô. last_event_seq chặn áp sự kiện cũ.

3. Quyền (PermissionCatalog) ​

Nhóm mới security trong app/Support/Authorization/PermissionCatalog.php:

QuyềnPhạm viDùng cho
security.viewtenantXem tổng quan, finding, kết quả kiểm tra, gói, ngoại lệ
security.managetenantCài đặt quét, cổng dự kiến, ngưỡng, ghi đè mức độ, yêu cầu quét sớm
security.hosts.managetenantTạo, thu hồi mã enroll Scanner; xem, gắn Server, thu hồi máy Scanner
security.exceptions.requesttenantTạo yêu cầu ngoại lệ
security.exceptions.approvetenantDuyệt, từ chối, thu hồi ngoại lệ (không duyệt yêu cầu của chính mình, trừ gói cá nhân)
security.exporttenantXuất CSV, XLSX, PDF
security.secrets.viewtenantXem đường dẫn, preview, chi tiết finding bí mật; xuất có cột bí mật. Không có quyền này chỉ thấy số đếm
security.pii.viewtenantXem bản đồ dữ liệu cá nhân, đường dẫn và số đếm theo tệp. Không có quyền này chỉ thấy tổng số
security.content.managetenantBật quét nội dung, dữ liệu cá nhân, chọn hồ sơ, gốc tùy chọn, khung giờ, detector tắt; mọi thay đổi có audit
security.matcherserviceChỉ tài khoản dịch vụ của secmatch. Phải được xử lý như COLLECTOR_PERMISSION hiện có: vai trò tùy chỉnh không chứa được, wildcard administrator bỏ qua, chỉ super admin cấp
platform.security.stats.viewplatformXem thống kê ẩn danh ở bảng điều khiển nền tảng

Vai trò có sẵn (đề xuất): administrator nhận mọi quyền tenant ở trên; infrastructure-engineer nhận thêm security.hosts.manage; auditor nhận security.view, security.pii.view; infrastructure-engineer nhận security.view, security.secrets.view, security.exceptions.request; vai trò dịch vụ mới security-matcher (SCOPE_SERVICE) chỉ có security.matcher; platform-ops, platform-auditor nhận platform.security.stats.view.

4. API ​

4.1 API cho secmatch (routes/security-matcher.php) ​

Tiền tố /api/v1/security/matcher, require từ routes/api.php thành nhóm riêng ngoài nhóm throttle:iac-api (như routes/monitoring-collector.php đã làm), Sanctum + allowlist IP của token, rate limiter riêng security-matcher.

Method, đường dẫnMục đích
POST /eventsNhận lô sự kiện (07 mục 6), tối đa 200, idempotent
PUT /vulnerabilitiesUpsert lô dữ liệu tham chiếu CVE (tóm tắt, CVSS, KEV, EPSS) cho các CVE có trong finding
GET /settings/{company_id}Cài đặt quét đã kẹp theo gói, có version; vai trò ingest dựng SecurityConfig từ đây (07 mục 8)
POST /scan-hosts/enrollIngest đổi mã enroll lấy máy Scanner: kiểm mã, tính năng security_scanning, hạn mức scan_hosts, gắn hoặc tạo Server; trả host_id, company_id, server_id (07 mục 3.0)
GET /scan-hosts?since=Bản sao registry cho ingest: khóa công khai, trạng thái, company_id, server_id, trạng thái giấy phép, version, scan_requested_at
POST /scan-hosts/{host_id}/rotate, POST /scan-hosts/{host_id}/seenXoay khóa công khai; cập nhật last_seen_at theo lô
POST /heartbeatPhiên bản, db_version, db_stale, độ sâu outbox, hiển thị cho nền tảng (không dữ liệu khách hàng)

Cấu hình quét đến máy qua vai trò ingest của secmatch (GET /scan/v1/config), không qua Collector (Q25).

4.2 API v1 cho người dùng (routes/api/security.php) ​

Chức năngEndpoint (tóm tắt)Quyền
Tổng quan, xu hướngGET /api/v1/security/overview, /trendssecurity.view
Finding: danh sách có lọc, chi tiết, lịch sử/api/v1/security/findingssecurity.view
Bảo mật của máy, gói của máy/api/v1/servers/{uuid}/security, /api/v1/servers/{uuid}/packagessecurity.view + servers.view
Tìm máy theo góiGET /api/v1/security/packages/searchsecurity.view
Ngoại lệ: tạo, duyệt, từ chối, thu hồi/api/v1/security/exceptions.request, .approve
Cài đặt, cổng dự kiến/api/v1/security/settings, /api/v1/security/expected-portssecurity.manage
XuấtPOST /api/v1/security/exportssecurity.export (cột nội dung cần thêm quyền xem tương ứng)
Finding bí mật, "cùng bí mật trên N máy"/api/v1/security/secrets, /api/v1/security/secrets/{uuid}/serverssecurity.secrets.view
Bản đồ dữ liệu cá nhân/api/v1/security/personal-data (theo máy, tệp, loại)security.pii.view
Cài đặt quét nội dung/api/v1/security/settings/contentsecurity.content.manage
Dịch vụ, phần mềm của máy; tìm máy theo dịch vụ, phần mềm/api/v1/servers/{uuid}/services, /api/v1/servers/{uuid}/software, /api/v1/security/software/searchsecurity.view + servers.view

Theo quy ước dự án: kiểm thử Pest cho mỗi endpoint, mẫu chạy thật tests/ApiSamples/NN_security.php, authorizeAbility(), QueuesApiExport cho xuất, HandlesApiTrash nếu cổng dự kiến dùng thùng rác.

5. Trang giao diện (Inertia, Vue) ​

TrangĐường dẫn đề xuấtGhi chú
Tổng quan bảo mậtresources/js/pages/security/overview/Index.vue06 mục 5.1
Danh sách finding, chi tiếtsecurity/findings/Index.vue, Show.vueBộ lọc máy dùng ô chọn tìm kiếm bất đồng bộ có phân trang
Ngoại lệsecurity/exceptions/Index.vue, Create.vueBiểu mẫu theo phong cách tạo mới hiện hành của dự án (nhiều biểu tượng, thẻ radio, chỉ báo bước như iac/Request.vue)
Cài đặt, cổng dự kiếnsecurity/Settings.vue, security/expected-ports/*Như trên
Tab Bảo mật của máy chủthêm vào servers/Show.vue06 mục 5.3
Finding bí mậtsecurity/secrets/Index.vue, Show.vueMức độ theo phơi nhiễm, "cùng bí mật trên N máy", hướng dẫn xoay vòng; mở chi tiết ghi audit
Bản đồ dữ liệu cá nhânsecurity/personal-data/Index.vueTheo máy, tệp, loại, chỉ số đếm; độ phủ quét
Cài đặt quét nội dungsecurity/settings/Content.vueBiểu mẫu theo phong cách tạo mới hiện hành (thẻ radio cho hồ sơ, chỉ báo bước); cảnh báo rõ khi thêm gốc tùy chọn
Tab Phần mềm và Dịch vụ của máythêm vào servers/Show.vueP6
Thống kê nền tảngplatform/security/Index.vueChỉ số ẩn danh
Trang tài liệu trong ứng dụngtrang docs công khai (kỹ thuật và hướng dẫn, vi và en)Gồm trang "Nguồn dữ liệu" với ghi công, thông báo NVD (03 mục 4)

6. Gói và hạn mức ​

Hạn mức đọc qua QuotaService::limit() và tính năng qua cơ chế tính năng của gói (PlanCatalog::FEATURE_KEYS, nhánh feat/biz-0). Scanner là gói cước riêng (Q25): số máy quét được đếm bằng hạn mức mới scan_hosts (máy Scanner chưa thu hồi), không dùng monitoring_agents. Enroll vượt hạn mức bị từ chối; hạ gói làm vượt hạn mức thì máy enroll sau cùng chuyển licence_inactive cho tới khi có chỗ.

Đề xuất khóa mới (chủ dự án chốt, Q10):

KhóaLoạiFreeProExpertTeamBusinessDedicated
security_scanningtính năngcócócócócócó
scan_hostsLIMIT_KEYS (đếm)152050200theo DeploymentLicense
security_hardening (kiểm tra AHS-*)tính năngkhôngcócócócócó
security_exceptions_approval (duyệt hai người)tính năngkhông áp dụng (tự duyệt)không áp dụngkhông áp dụngcócócó
security_reports_pdftính năngkhôngkhôngcócócócó
security_custom_slatính năngkhôngcócócócócó
security_history_daysSETTING_LIMIT_KEYS3090180180365không giới hạn
security_scan_min_interval_hoursSETTING_LIMIT_KEYS24246611
security_secret_scanningtính năngkhông (chỉ số đếm)cócócócócó
security_pii_scanningtính năngkhôngkhôngcócócócó
security_software_inventory (dịch vụ, phần mềm, tệp đáng chú ý)tính năngcócócócócócó
security_content_custom_rootsSETTING_LIMIT_KEYS04881616
  • Free, Pro, Expert có users = 1 trong PlanCatalog::defaults(), nên duyệt hai người không thể có: tự duyệt có lý do và hạn (06 mục 6).
  • Dedicated lấy hạn mức và tính năng từ DeploymentLicense (payload ký, kiểm tra offline): khóa mới phải có trong payload giấy phép triển khai.
  • Hạ gói: tính năng tắt thì ngừng quét mới, dữ liệu cũ chỉ đọc; xóa theo security_history_days mới sau thời gian ân hạn 30 ngày, cùng chính sách đã chốt cho retention số liệu giám sát (Q17 của Collector).
  • Đổi gói nâng version của cài đặt và registry máy Scanner; ingest thấy ở lần đồng bộ kế tiếp (60 giây) và đổi ETag GET /scan/v1/config.

7. Thông báo, webhook, audit ​

Mẫu thông báo mặc định (vi, en) qua NotificationTemplate, NotificationPreference, WebhookChannel hiện có:

Sự kiệnMặc định gửi tới
security.finding.p1_opened (gồm CVE vào KEV làm finding thành P1)Người có security.manage
security.digest.daily (finding ưu tiên P2 mới, đã đóng, sắp quá hạn)Người có security.view đã đăng ký
security.sla.due_soon, security.sla.overdueNgười có security.manage
security.exception.requested, .decided, .expiring, .expiredNgười duyệt, người yêu cầu
security.server.scan_stale (máy Scanner đang hoạt động mà quá 48 giờ không có báo cáo)Người có security.manage
security.db.stale (Dedicated, DB quá ngưỡng)Quản trị viên công ty on-prem
security.secret.high_opened (bí mật mức critical hoặc high mới)Người có security.secrets.view. Nội dung: mã detector, mức độ, tên máy, liên kết; không đường dẫn, preview, fingerprint
security.pii.bulk_found (tệp mới có dữ liệu cá nhân từ ngưỡng thứ hai)Người có security.pii.view. Chỉ số đếm và tên máy
security.content.scope_changed (gốc tùy chọn, bật dữ liệu cá nhân)Mọi người có security.content.manage

Payload webhook: uuid finding, uuid và tên máy, vuln_id hoặc detector_id, ưu tiên, risk, fixed_version, liên kết. Không bí mật, không bằng chứng thô, không đường dẫn, preview, fingerprint của finding nội dung. Chuông thời gian thực (Reverb) cho P1. Audit qua AuditRecorder: cài đặt (gồm phạm vi quét nội dung, xoay K_company), cổng dự kiến, ngoại lệ (tạo, duyệt, từ chối, thu hồi), xuất, mở chi tiết finding bí mật (Q41). Sự kiện finding do hệ thống sinh ghi vào security_finding_events, không ghi audit từng sự kiện.

8. Thống kê nền tảng ẩn danh ​

Job ban đêm chạy trong ngữ cảnh hệ thống, đọc security_findings, security_server_scans (đếm theo company_id chỉ trong bộ nhớ để áp ngưỡng k), ghi platform_security_stats_daily không có định danh công ty. Chỉ số nội dung chỉ là số đếm theo họ detector, mức độ, mức phơi nhiễm; không đường dẫn, fingerprint, preview. Ngưỡng k mặc định 5 (Q13). Trang nền tảng chỉ đọc bảng này và GET /internal/v1/stats/global của secmatch. Kiểm thử: bảng không có cột định danh công ty, mục dưới ngưỡng k không xuất hiện, người có vai trò nền tảng không gọi được endpoint tenant.

9. Vòng đời và dọn dẹp ​

  • Xóa vĩnh viễn Server: trong cùng giao dịch xóa security_* của máy; sau commit dispatch job gọi DELETE /internal/v1/servers/{id}/data?company_id= của secmatch (tries 10, backoff như HUB-14).
  • Purge Company (gồm từng công ty con): như trên với DELETE /internal/v1/companies/{id}/data, gọi một lần cho mỗi company_id.
  • Sự kiện đến muộn cho máy đã xóa: trả rejected với unknown_server, không 5xx.
  • Lệnh dọn định kỳ theo mẫu lệnh dọn hiện có: security_finding_events và finding đã đóng quá security_history_days.

10. Danh sách việc HUB-SEC ​

MãViệcP
HUB-SEC-1Quyền nhóm security, vai trò dịch vụ security-matcher xử lý như monitoring.collector (vai trò tùy chỉnh không chứa được), quyền nền tảng1
HUB-SEC-2Migration, model, factory cho bảng mục 2 (theo giai đoạn)1 đến 7
HUB-SEC-3routes/security-matcher.php, rate limiter, POST /events, PUT /vulnerabilities, GET /settings, POST /heartbeat1
HUB-SEC-4Tab Bảo mật trên trang máy chủ, SecmatchClient (timeout, thử lại, ngắt mạch)1
HUB-SEC-5Tổng quan bảo mật, xu hướng, security_stats_daily3, 7
HUB-SEC-6Danh sách finding, chi tiết, tìm máy theo gói1 (cơ bản), 3 (đầy đủ)
HUB-SEC-7Ngoại lệ: model, luồng duyệt, hết hạn tự động, giao diện; phạm vi detector cộng mẫu đường dẫn, fingerprint7
HUB-SEC-8Mẫu thông báo vi, en, digest, webhook3 (ưu tiên P1, SLA), 7 (còn lại)
HUB-SEC-9Xuất CSV, XLSX (giai đoạn P3), PDF (giai đoạn P7, cần duyệt phụ thuộc mới)3, 7
HUB-SEC-10API v1 routes/api/security.php, mẫu tests/ApiSamples3, 7
HUB-SEC-11Gói và hạn mức: khóa mới trong PlanCatalog, kẹp cài đặt, payload DeploymentLicense, reload cấu hình khi đổi gói3
HUB-SEC-12Thống kê nền tảng ẩn danh (gồm số đếm nội dung)7
HUB-SEC-13Purge máy và công ty gọi secmatch1
HUB-SEC-14Cài đặt quét, cổng dự kiến, ghi đè mức độ, GET /settings/{company_id} cho ingest5
HUB-SEC-15Trang tài liệu trong ứng dụng (kỹ thuật và hướng dẫn, vi, en), trang Nguồn dữ liệu1 đến 7
HUB-SEC-16Tính risk, priority, SLA phía Access Hub, tính lại khi thuộc tính máy đổi; phần 16b cho finding nội dung3
HUB-SEC-17Quét bí mật: quyền security.secrets.view, security.content.manage, cột nội dung, K_company (sinh, ENC-2, phát xuống, xoay), cài đặt quét nội dung, trang finding bí mật, "cùng bí mật trên N máy", audit khi xem, thông báo không giá trị, tài liệu2
HUB-SEC-18Dữ liệu cá nhân: quyền security.pii.view, bật theo công ty, bản đồ dữ liệu cá nhân, thông báo, tài liệu gồm phần nghĩa vụ của khách hàng4
HUB-SEC-19Kiểm kê mở rộng: tab Phần mềm và Dịch vụ, tìm máy theo dịch vụ, phần mềm, thống kê tệp, tệp đáng chú ý6
HUB-SEC-20Container, image9
HUB-SEC-21Máy Scanner: bảng scan_hosts, scan_enrolment_codes; quyền security.hosts.manage; trang tạo mã enroll (hiện lệnh cài, mã một lần), danh sách máy Scanner, thu hồi; POST /scan-hosts/enroll, GET /scan-hosts?since=, xoay khóa; hạn mức scan_hosts; trang máy chủ hiển thị cả Access Hub Agent và máy Scanner (nếu có) với trạng thái riêng; kiểm thử hai công ty, mã hết hạn, dùng lại, vượt hạn mức1

Định nghĩa hoàn thành cho mỗi HUB-SEC: như danh sách hoàn thành của HUB-1 đến HUB-18 (access-hub-collector/docs/06 mục 9, chỉ mượn tiêu chí) (Pest, mẫu API, trang tài liệu vi và en, khóa dịch đủ hai locale, Pint, PHPStan, ESLint, vue-tsc, php artisan queue:restart khi đụng job hoặc thông báo), cộng kiểm thử hai công ty cho mọi endpoint và job, rà soát cô lập tenant trước khi hợp nhất, và với finding nội dung: kiểm thử rằng không API, trang, thông báo, xuất nào trả giá trị (chỉ các trường ADR 0011) và người thiếu quyền xem chỉ thấy số đếm.

11. Đặc tả chi tiết HUB-SEC giai đoạn P1 ​

Mục này là bản đặc tả để nhóm Access Hub làm ngay phần P1, khớp với secmatch đã cài (internal/secmatch). Phần nào secmatch chưa gửi được ghi rõ là để sau; Access Hub không cần làm trước.

11.1 Phạm vi P1 ​

MãPhần P1Để sau
HUB-SEC-1Quyền security.view, security.matcher (dịch vụ), vai trò security-matcherQuyền ngoại lệ, xuất, nội dung
HUB-SEC-2Bảng security_findings, security_finding_events, security_server_scansCác bảng còn lại
HUB-SEC-3POST /api/v1/security/matcher/events, GET /settings/{company_id} (ingest cần)PUT /vulnerabilities, POST /heartbeat: secmatch chưa gọi
HUB-SEC-4Tab Bảo mật của máy chủ, SecmatchClient
HUB-SEC-6Danh sách finding cơ bản có lọc, tìm máy theo góiChi tiết đầy đủ, risk, SLA (P3)
HUB-SEC-13Xóa máy, purge công ty gọi secmatch
HUB-SEC-21Mã enroll, registry máy Scanner, hạn mức scan_hosts, liên kết Server, API cho ingestXoay khóa tự động
HUB-SEC-15Trang tài liệu vi, en (gồm trang Nguồn dữ liệu, ghi công CC BY-SA 4.0 của Ubuntu)

Không có risk, priority, SLA, ngoại lệ, thông báo trong P1. Giao diện hiển thị severity_label của distro và fix_status.

11.2 Phong bì và lô ​

POST /api/v1/security/matcher/events, Content-Type: application/json, Authorization: Bearer <Sanctum token của tài khoản security-matcher>.

json
{"events": [
  {"event_id": "9c1e...64 hex", "type": "finding.opened", "company_id": "c1...", "server_id": "s1...",
   "seq": 42, "occurred_at": "2026-10-02T13:00:00Z", "payload": {"...": "..."}}
]}
  • Tối đa 200 sự kiện mỗi lô. Secmatch chỉ đặt sự kiện của một công ty trong một lô, nhưng Access Hub vẫn kiểm từng sự kiện.
  • event_id: 64 ký tự hex, duy nhất toàn cục. Gửi lặp (secmatch thử lại sau 5xx, timeout) phải trả kết quả như lần đầu và không áp lại.
  • seq: tăng chặt theo máy (chung cho mọi loại sự kiện của máy đó). Dùng để bỏ sự kiện cũ đến muộn.
  • host_id luôn có; server_id là null khi máy Scanner chưa gắn Server (07 mục 3.0), Access Hub gắn finding vào máy Scanner qua host_id cho tới khi gắn. company_id, server_id: lấy từ registry máy Scanner (scan_hosts), do Access Hub cấp lúc enroll; server_id là định danh của Server chung, không phải agent_id giám sát.

11.3 Payload theo loại ​

finding.opened và finding.updated (cùng hình dạng; updated gửi khi một trường trong danh sách "đổi" bên dưới thay đổi):

TrườngKiểuGhi chú
finding_keyhex 64Khóa ổn định của finding, đã gồm company_id, server_id
kind"vulnerability", "release_eol"Xem bảng bản phát hành hết hỗ trợ ở cuối mục
vuln_idchuỗiCVE-...; Debian có thể có TEMP-...
aliases, advisory_idsmảng chuỗiadvisory_ids gồm USN-..., DSA-..., DLA-...; luôn là mảng
ecosystemchuỗiubuntu:24.04, debian:12
package_keychuỗiGói nguồn (kernel: linux hoặc biến thể)
packagesmảng {name, version, arch}Gói nhị phân đã cài thuộc gói nguồn đó
installed_versionchuỗiPhiên bản thấp nhất đang cài của gói nguồn
fixed_versionchuỗi, có thể rỗngRỗng khi chưa có bản sửa
fix_statusfixed, no_fix, wont_fix, undetermined, upgrade_releasefixed nghĩa là có bản sửa mà máy chưa cài; upgrade_release chỉ cho kind = release_eol
fix_channelstandard, esm, eltsesm: bản sửa chỉ có qua Ubuntu Pro; elts: chỉ qua Debian ELTS trả phí
severity_labelchuỗi, có thể rỗngMức của distro, chữ thường: Ubuntu negligible, low, medium, high, critical; Debian là urgency của tracker viết thường, thường gặp unimportant, low, medium, high, not yet assigned, end-of-life
minorboolDebian no-dsa, unimportant: ưu tiên thấp
kernelboolFinding của kernel đang chạy
reboot_requiredboolBản sửa đã cài nhưng kernel cũ còn chạy
no_distro_fixboolBản phát hành hết hỗ trợ, distro sẽ không sửa
eol_date, upgrade_tochuỗi, mảng chuỗiChỉ có giá trị với kind = release_eol; rỗng ở finding khác
cvss_score, cvss_vector, score_sourcesố, chuỗi, chuỗiChỉ có khi DB có điểm (NVD, chưa bật ở P1): trường có thể vắng
kev, epssfalse, nullGiữ chỗ, P3
first_seen_atRFC3339Lần đầu secmatch thấy finding
db_versionsốPhiên bản DB lỗ hổng đã dùng

Trường "đổi" sinh finding.updated: installed_version, fixed_version, fix_status, fix_channel, severity_label, reboot_required, minor, packages (tên và phiên bản), advisory_ids. Điểm CVSS và bí danh đổi không sinh updated ở P1.

finding.resolved: finding_key, kind, resolved_reason (package_updated, package_removed, advisory_changed, out_of_scope, release_upgraded), resolved_at, db_version. out_of_scope nghĩa là máy không còn được so khớp (đổi sang hệ không hỗ trợ, bản phát hành hết hỗ trợ).

server.scanned: scanned_at, scanner_version, db_version, os {id, version_id, codename}, kernel_running, reboot_required, livepatch_active, package_count, error_codes (mảng, xem contract/security-report-v1.md mục 6), match_status (ok, unsupported_os, unsupported_release, release_eol, no_db), release_support (standard, esm_only, eol hoặc rỗng), open_findings. Chỉ gửi khi có báo cáo mới của máy (không gửi khi so khớp lại vì DB đổi).

Hiển thị match_status: "Hệ điều hành chưa được hỗ trợ", "Chưa có dữ liệu lỗ hổng", và với release_eol: "Bản phát hành đã hết hỗ trợ bảo mật". Chính sách của chủ dự án (2026-10-02): lỗ hổng vẫn là lỗ hổng. Máy chạy bản phát hành hết hỗ trợ vẫn nhận mọi finding (finding không bị đóng với out_of_scope), cộng một finding release_eol.

Finding của bản phát hành hết hỗ trợ:

TrườngÝ nghĩa
no_distro_fix (mọi finding, bool)Distro sẽ không phát hành bản sửa: finding chưa sửa trên bản hết hỗ trợ, hoặc bản sửa chỉ có ở ELTS trả phí. Giao diện ghi "Distro sẽ không sửa"
fix_channel = eltsBản sửa chỉ có qua Debian ELTS trả phí (Freexian), như esm của Ubuntu Pro
kind = release_eolMột finding cho mỗi máy: vuln_id dạng AHS-EOL-DEBIAN-11, package_key rỗng, fix_status = upgrade_release, severity_label = high, eol_date (YYYY-MM-DD), upgrade_to (các bản phát hành đang hỗ trợ của distro, ví dụ ["debian:12", "debian:13"]). Hiển thị nổi bật trên tab Bảo mật và tổng quan: "Nâng cấp lên bản phát hành được hỗ trợ", kèm ngày hết hỗ trợ

Finding release_eol đóng với resolved_reason = release_upgraded khi máy báo cáo bản phát hành khác (nâng cấp xong).

11.4 Xử lý mỗi lô ​

Trong một giao dịch mỗi lô:

  1. Kiểm phong bì: JSON hợp lệ, events là mảng 1 đến 200, mỗi sự kiện có đủ trường với kiểu đúng. Sai phong bì thì 422 cả lô.
  2. Với từng sự kiện:
    1. event_id đã có trong security_finding_events: đưa vào accepted, không làm gì.
    2. server_id không thuộc company_id, hoặc máy đã xóa, hoặc máy Scanner của nó ở trạng thái revoked: rejected với unknown_server.
    3. type lạ: rejected với unsupported_type. Payload thiếu trường bắt buộc: invalid_payload.
    4. Sự kiện finding: tìm security_findings theo (company_id, finding_key). Nếu có và seq <= last_event_seq: ghi nhật ký, accepted, không đổi finding (sự kiện cũ).
      • opened, updated: upsert mọi cột của payload, status = open, resolved_at, resolved_reason về null, last_seen_at = occurred_at, last_event_seq = seq. opened cho finding đang resolved là mở lại. updated cho finding chưa có thì tạo như opened (secmatch có thể phát lại sau sự cố).
      • resolved: nếu có thì status = resolved, resolved_at, resolved_reason, last_event_seq = seq; nếu chưa có thì chỉ ghi nhật ký.
    5. server.scanned: upsert security_server_scans theo (company_id, server_id) nếu seq lớn hơn last_event_seq của dòng đó.
    6. Ghi security_finding_events (event_id unique), accepted.
  3. Trả 200 {"data": {"accepted": ["<event_id>", ...], "rejected": [{"event_id": "...", "reason": "unknown_server"}]}}.

Mã HTTP: 200 (kể cả khi có rejected), 401, 403 (token sai, thiếu quyền security.matcher), 422 (phong bì sai), 429 (rate limiter security-matcher, đề xuất 600 request mỗi phút), 5xx. Secmatch hiện xử lý: 2xx là đã giao (không thử lại sự kiện trong rejected), 429 và 5xx thử lại cả lô theo thứ tự, 4xx khác chuyển dead-letter. Vì vậy mọi lỗi tạm thời phía Access Hub (khóa, deadlock, DB không sẵn) phải trả 5xx, không trả 4xx.

POST /internal/v1/resync?company_id= của secmatch phát lại finding.opened cho mọi finding đang mở của công ty với seq mới: dùng để khôi phục sau sự cố. Finding Access Hub còn mở mà resync không phát lại thì giữ nguyên (P3 thêm đối soát).

11.5 SecmatchClient ​

Theo mẫu MonitoringCollectorClient: base URL và token admin riêng trong config (không trong DB), timeout kết nối 2 giây, đọc 5 giây, thử lại 2 lần với GET, ngắt mạch sau 5 lỗi liên tiếp trong 60 giây. Mọi lời gọi truyền company_id lấy từ Server hoặc phiên, không từ input người dùng.

Dùng ởGọiPhản hồi
Tab Bảo mật, danh sách gói của máyGET /internal/v1/servers/{server_id}/packages?company_id=&q=&cursor=&limit= (limit tối đa 500){"data": {"items": [{server_id, name, version, arch, source_name, source_version, ecosystem}], "next_cursor"}}; 404 not_found khi máy chưa có inventory hoặc không thuộc công ty
Tìm máy theo góiGET /internal/v1/companies/{company_id}/packages/search?name=&version_lt=&version_gte=&ecosystem=&cursor=&limit=Cùng hình dạng, mỗi dòng một máy
Thẻ độ phủ trên trang tổng quanGET /internal/v1/companies/{company_id}/summary{"data": {servers, oldest_report_ms, ecosystems: {"ubuntu:24.04": 3, "release_eol": 1}, open_findings}}
Xóa máy (HUB-SEC-13)DELETE /internal/v1/servers/{server_id}/data?company_id=204, idempotent
Purge công tyDELETE /internal/v1/companies/{company_id}/data204, idempotent; secmatch giữ bia mộ để từ chối báo cáo nhận trước giờ xóa
Nút khôi phục cho quản trị (tùy chọn)POST /internal/v1/resync?company_id=200 {"data": {"events": n}}

Lỗi trả dạng {"error": {"code", "message"}}. Secmatch không sẵn sàng thì tab hiển thị "Không có dữ liệu", không lỗi 500.

11.6 Kiểm thử bắt buộc cho P1 ​

  1. Lô có sự kiện của hai công ty và server_id chéo: chỉ sự kiện đúng công ty được áp, sự kiện chéo unknown_server.
  2. Gửi lại cùng lô: kết quả giống hệt, không bản ghi trùng.
  3. Đảo thứ tự opened (seq 5) và resolved (seq 6): finding cuối cùng resolved.
  4. resolved rồi opened mới hơn: finding mở lại, resolved_at null.
  5. Tài khoản không có security.matcher, tài khoản vai trò tùy chỉnh chứa security.matcher: 403.
  6. Danh sách finding và tab máy chủ: người công ty A không thấy finding, máy, gói của B (gồm qua SecmatchClient với company_id của A và server_id của B: secmatch trả 404).
  7. Xóa máy và purge công ty gọi secmatch sau commit, thử lại khi secmatch lỗi.
  8. Mẫu chạy thật tests/ApiSamples/NN_security.php gửi một lô thật từ fixture (dùng accesshub-secmatch chạy cục bộ với DB thử, hoặc payload ghi sẵn trong testdata/golden).
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-scanner lúc 10:57, 03/10/2026. Khi tài liệu và mã khác nhau, mã thắng.