@php $filteredDisks = collect($reportData['disk_info'] ?? [])->reject( fn($d) => str_starts_with($d['filesystem'] ?? '', '/dev/loop') || str_starts_with($d['mounted_on'] ?? '', '/snap/') )->values(); $rootDisk = null; foreach ($filteredDisks as $disk) { if (($disk['mounted_on'] ?? '') === '/') { $rootDisk = $disk; break; } } $ssh = $reportData['ssh_config'] ?? []; $pwd = $reportData['password_policy'] ?? []; $as = $reportData['apache_security'] ?? []; $ws = $reportData['web_service'] ?? []; $hdr = $ws['http_headers'] ?? []; $tls = $ws['ssl_tls'] ?? []; $sslDays = isset($ws['ssl_cert_days_left']) ? intval($ws['ssl_cert_days_left']) : null; $tlsGrade = null; if (!empty($tls)) { $g = 'A'; if ($sslDays !== null && $sslDays <= 0) { $g = 'F'; } elseif ($tls['weak_cipher'] ?? false) { $g = 'C'; } elseif ($tls['sslv3'] ?? false) { $g = 'C'; } elseif (($tls['tls10'] ?? false) || ($tls['tls11'] ?? false)) { $g = 'B'; } elseif (($tls['tls13'] ?? false) && ($tls['forward_secrecy'] ?? false) && !empty($hdr['hsts'])) { $g = 'A+'; } $tlsGrade = $g; } $gradeColor = match($tlsGrade) { 'A+' => '#00c853', 'A' => '#43a047', 'B' => '#f9a825', 'C' => '#ef6c00', 'F' => '#c62828', default => '#9e9e9e' }; if (!function_exists('ev')) { function ev($raw, $pattern) { return preg_match($pattern, $raw ?? '', $m) ? $m[1] : ($raw ?: 'N/A'); } } @endphp {{ $host->name }} - 主機維護報告

主機維護安全檢查報告

主機:{{ $host->name }} ・ IP:{{ $reportData['ip'] ?? 'N/A' }} ・ OS:{{ $host->os_type === 'windows' ? 'Windows' : 'Linux' }} ・ 報告時間:{{ $reportDate }}

1. 基本系統資訊

作業系統{{ $reportData['os_release']['PRETTY_NAME'] ?? ($reportData['os'] ?? 'N/A') }}
核心版本{{ $reportData['kernel_version'] ?? 'N/A' }}
主機名稱{{ $reportData['hostname'] ?? 'N/A' }}
IP 位址{{ $reportData['ip'] ?? 'N/A' }}
時區{{ $reportData['timezone'] ?? 'N/A' }}
開機時間{{ $reportData['boot_time'] ?? 'N/A' }}

2. 硬體資訊

@foreach($filteredDisks as $disk) @endforeach
CPU 型號{{ $reportData['cpu_model'] ?? 'N/A' }}
CPU 數量{{ $reportData['cpu_count'] ?? 'N/A' }} 核心
記憶體@if(isset($reportData['memory']))總容量 {{ $reportData['memory']['total_gb'] ?? '?' }} GB,已用 {{ $reportData['memory']['used_gb'] ?? '?' }} GB,可用 {{ $reportData['memory']['free_gb'] ?? '?' }} GB({{ $reportData['memory']['percent'] ?? '?' }}%)@else N/A @endif
磁碟 {{ $disk['mounted_on'] ?? '?' }} {{ $disk['filesystem'] ?? '' }} 總量 {{ $disk['size'] ?? '?' }},已用 {{ $disk['used'] ?? '?' }}({{ $disk['percent'] ?? '?' }}),可用 {{ $disk['avail'] ?? '?' }}

3. 網路與服務資訊

Web 服務{{ $ws['type'] ?? ev($reportData['apache_version'] ?? '', '/Apache\/([\d\.]+)/') }}
PHP{{ $reportData['php_version'] ?? 'N/A' }}
MySQL{{ ev($reportData['mysql_version'] ?? '', '/([\d\.]+)/') }}
OpenSSL{{ $reportData['openssl_version'] ?? 'N/A' }}
OpenSSH{{ $reportData['openssh_version'] ?? 'N/A' }}
Python{{ $reportData['python_version'] ?? 'N/A' }}
GCC{{ $reportData['gcc_version'] ?? 'N/A' }}
NTP 校時{!! (($reportData['ntp_status'] ?? '') === 'synchronized' || ($reportData['ntp_status'] ?? '') === 'active') ? '✔ 已同步' : '✘ ' . ($reportData['ntp_status'] ?? 'N/A') . '' !!}@if(!empty($reportData['ntp_servers']))({{ implode(', ', $reportData['ntp_servers']) }})@endif

4. 帳號管理

特權帳號{{ !empty($reportData['privileged_accounts']) ? implode(', ', $reportData['privileged_accounts']) : 'N/A' }}

5. 掃毒狀態

掃毒軟體{!! !empty($reportData['antivirus_installed']) ? '✔ 已安裝' : '✘ 未安裝' !!}
版本{{ $reportData['antivirus_version'] ?? 'N/A' }}

6. 防火牆設定

類型{{ strtoupper($reportData['firewall_type'] ?? 'N/A') }}
狀態{!! ($reportData['firewall_status'] ?? '') === 'active' ? '✔ 已啟用' : '✘ ' . ($reportData['firewall_status'] ?? 'N/A') . '' !!}

7. SSH 安全設定

SSH Port{{ $ssh['port'] ?? '22' }}
Root 登入@if(($ssh['permit_root_login'] ?? '') === 'no')✔ 已禁止@elseif(($ssh['permit_root_login'] ?? '') === 'prohibit-password')僅允許金鑰@else{{ $ssh['permit_root_login'] ?? 'unknown' }}@endif
密碼認證@if(($ssh['password_auth'] ?? '') === 'no')✔ 已關閉@else{{ $ssh['password_auth'] ?? 'unknown' }}@endif
最大嘗試次數{{ $ssh['max_auth_tries'] ?? 'unknown' }}

8. 密碼政策

最長有效天數{{ $pwd['max_days'] ?? 'N/A' }} 天
最短更改間隔{{ $pwd['min_days'] ?? 'N/A' }} 天
最短長度{{ $pwd['min_length'] ?? ($pwd['pam_minlen'] ?? 'N/A') }}
密碼複雜度{!! !empty($pwd['pam_pwquality']) ? '✔ 已啟用 (pam_pwquality)' : '✘ 未設定' !!}

9. fail2ban 入侵防護

@if(!empty($reportData['fail2ban_jails']))@endif
狀態{!! ($reportData['fail2ban_status'] ?? '') === 'active' ? '✔ 已啟用' : '✘ ' . ($reportData['fail2ban_status'] ?? 'N/A') . '' !!}
防護規則{{ $reportData['fail2ban_jails'] }}

10. 系統更新狀態

上次更新{{ $reportData['last_update'] ?? 'N/A' }}
待更新套件{!! ($reportData['pending_updates'] ?? 0) == 0 ? '✔ 已是最新' : '' . $reportData['pending_updates'] . ' 個待更新' !!}
安全更新{!! ($reportData['security_updates'] ?? 0) == 0 ? '✔ 無待處理安全更新' : '' . $reportData['security_updates'] . ' 個安全更新待處理' !!}
@if(!empty($as))

11. Apache 安全設定

ServerTokens{!! strtolower($as['server_tokens'] ?? '') === 'prod' ? '✔ Prod(隱藏版本)' : '' . ($as['server_tokens'] ?? 'unknown') . '' !!}
ServerSignature{!! strtolower($as['server_signature'] ?? '') === 'off' ? '✔ Off' : '' . ($as['server_signature'] ?? 'unknown') . '' !!}
TraceEnable{!! strtolower($as['trace_enable'] ?? '') === 'off' ? '✔ Off' : '' . ($as['trace_enable'] ?? 'unknown') . '' !!}
@endif @if(!empty($hdr))

11b. HTTP 資安標頭

@php $hdrs = [ 'x_frame_options' => ['X-Frame-Options', true], 'x_content_type' => ['X-Content-Type-Options', true], 'x_xss_protection' => ['X-XSS-Protection', false], 'content_security_policy' => ['Content-Security-Policy', true], 'hsts' => ['Strict-Transport-Security', true], 'referrer_policy' => ['Referrer-Policy', false], 'permissions_policy' => ['Permissions-Policy', false], ]; @endphp @foreach($hdrs as $key => [$label, $required]) @endforeach
Header狀態內容
{{ $label }} {!! !empty($hdr[$key]) ? '✔ 已設定' : ($required ? '✘ 未設定' : '✘ 未設定') !!} {{ !empty($hdr[$key]) ? Str::limit($hdr[$key], 100) : '' }}
@endif

12. 存取控制機制(MAC)

類型{{ $reportData['mac_type'] ?? 'N/A' }}
狀態{!! in_array(strtolower($reportData['mac_status'] ?? ''), ['enabled','enforcing']) ? '✔ ' . $reportData['mac_status'] . '' : '' . ($reportData['mac_status'] ?? 'N/A') . '' !!}

13. Log 管理設定

Logrotate(180 天){!! !empty($reportData['log_rotate_180days']) ? '✔ 已設定' : '✘ 未設定' !!} {{ $reportData['log_rotate_detail'] ?? '' }}
Apache Logrotate{!! !empty($reportData['apache_logrotate_180days']) ? '✔ 已設定' : '✘ 未設定' !!} {{ $reportData['apache_logrotate_detail'] ?? '' }}

14. 螢幕保護設定

@php $timeout = $reportData['screensaver_timeout'] ?? ''; if(preg_match('/uint32\s+(\d+)/', $timeout, $m)) { $s=intval($m[1]); $timeout = $s . ' 秒(約 ' . round($s/60,1) . ' 分鐘)'; } @endphp
啟用狀態{!! !empty($reportData['screensaver_configured']) ? '✔ 已設定' : '✘ 未設定' !!}
等待時間{{ $timeout ?: 'N/A' }}
@if(!empty($reportData['accounts_detail']))

15. 帳號安全檢查

@foreach($reportData['accounts_detail'] as $acct) @php $c = $acct['chage'] ?? []; @endphp @endforeach
帳號SudoShell群組最後更改密碼到期帳號到期最大間隔
{{ $acct['user'] }} {!! !empty($acct['is_sudo']) ? 'sudo' : '-' !!} {{ basename($c['shell'] ?? '') ?: '-' }} {{ $acct['groups'] ?? '-' }} {{ $c['last_change'] ?? 'N/A' }} {!! ($c['pw_expires'] ?? 'never') === 'never' ? 'never' : $c['pw_expires'] !!} {!! ($c['acct_expires'] ?? 'never') === 'never' ? 'never' : $c['acct_expires'] !!} {{ $c['max_days'] ?? 'N/A' }}
@endif @if(!empty($reportData['last_logins']))

16. 最近登入紀錄

@if(!empty($reportData['failed_login_count']))

失敗登入次數:{{ $reportData['failed_login_count'] }} 次

@endif
{{ $reportData['last_logins'] }}
@endif @if(!empty($reportData['listening_ports_parsed']))

17. 對外開放 Port 清單

@foreach($reportData['listening_ports_parsed'] as $p) @endforeach
協定Port服務監聽位址
{{ $p['protocol'] ?? '' }}{{ $p['port'] ?? '' }}{{ $p['service'] ?? '-' }}{{ $p['address'] ?? '' }}
@endif @if(!empty($reportData['cron_jobs']))

18. 系統排程

@foreach($reportData['cron_jobs'] as $cj) @endforeach
來源排程內容
{{ $cj['source'] }}{{ $cj['job'] ?? $cj['command'] ?? '' }}
@endif @if(!empty($reportData['apache_sites_certificates']['exists']))

19. 子站 SSL 憑證資訊

@foreach($reportData['apache_sites_certificates']['details'] ?? [] as $site) @endforeach
站台憑證檔案到期日
{{ $site['name'] ?? 'N/A' }}{{ $site['certificate_file'] ?? 'N/A' }}{{ $site['certificate_expiry'] ?? 'N/A' }}
@endif

20. SSL/TLS 安全分析(Agent 本機)

@if(empty($tls))

Agent 尚未回報 SSL/TLS 資料,或此主機無 Web 服務。

@else
TLS 等級{{ $tlsGrade }}
憑證剩餘天數{!! $sslDays !== null ? ($sslDays <= 0 ? '已過期' : ($sslDays <= 30 ? '' . $sslDays . ' 天' : '' . $sslDays . ' 天')) : 'N/A' !!}
憑證位元數{{ $tls['cert_bits'] ?? 'N/A' }}
簽章演算法{{ $tls['cert_sig'] ?? 'N/A' }}
發行者{{ $tls['cert_issuer'] ?? 'N/A' }}
Forward Secrecy{!! ($tls['forward_secrecy'] ?? false) ? '✔ 支援' : '✘ 不支援' !!}
弱加密{!! ($tls['weak_cipher'] ?? false) ? '✘ 偵測到弱加密' : '✔ 未偵測到弱加密' !!}

TLS 協議支援

@foreach([['SSLv3','sslv3',true],['TLS 1.0','tls10',true],['TLS 1.1','tls11',true],['TLS 1.2','tls12',false],['TLS 1.3','tls13',false]] as [$label,$key,$dangerous]) @endforeach @foreach([['SSLv3','sslv3',true],['TLS 1.0','tls10',true],['TLS 1.1','tls11',true],['TLS 1.2','tls12',false],['TLS 1.3','tls13',false]] as [$label,$key,$dangerous]) @endforeach
{{ $label }}
@if($tls[$key] ?? false) {!! $dangerous ? '✔ 支援' : '✔ 支援' !!} @else {!! $dangerous ? '✘ 停用' : '✘ 停用' !!} @endif
@endif @if(!empty($sslReport) && empty($sslReport['error'])) @php $ssl = $sslReport; $cert = $ssl['certificate'] ?? []; $daysLeft = $ssl['days_left'] ?? null; $gc = match($ssl['grade'] ?? 'F') { 'A+','A' => '#198754', 'B' => '#0d6efd', 'C' => '#fd7e14', default => '#dc3545' }; @endphp

21. SSL Labs 外部評測

評等{{ $ssl['grade'] ?? 'N/A' }}({{ $ssl['score'] ?? 0 }}/100 分)
憑證主體{{ $cert['subject'] ?? 'N/A' }}
有效期限{{ $cert['not_before'] ?? '' }} ~ {{ $cert['not_after'] ?? '' }}@if($daysLeft !== null)(剩餘 {{ $daysLeft }} 天)@endif
Cipher{{ $ssl['cipher'] ?? 'N/A' }}
HTTP/2{{ !empty($ssl['http2']) ? '✔ 支援' : '✘ 不支援' }}
@endif @if(!empty($host->av_last_scan)) @php $av = $host->av_last_scan; $avStatus = $av['status'] ?? 'unknown'; $avColor = $avStatus === 'clean' ? '#27ae60' : ($avStatus === 'infected' ? '#e74c3c' : '#95a5a6'); $avLabel = $avStatus === 'clean' ? '乾淨' : ($avStatus === 'infected' ? '發現威脅' : '錯誤'); $duration = $av['duration_seconds'] ?? null; $durationStr = $duration !== null ? ($duration >= 3600 ? sprintf('%d 時 %d 分 %d 秒', intdiv($duration,3600), intdiv($duration%3600,60), $duration%60) : ($duration >= 60 ? sprintf('%d 分 %d 秒', intdiv($duration,60), $duration%60) : $duration . ' 秒')) : null; @endphp

22. 掃毒結果(ClamAV)

@if($durationStr)@endif
掃描狀態{{ $avLabel }}
開始時間{{ $av['started_at'] ?? $av['scanned_at'] ?? 'N/A' }}
結束時間{{ $av['finished_at'] ?? 'N/A' }}
掃描耗時{{ $durationStr }}
掃描路徑{{ implode('、', $av['paths'] ?? []) }}
掃描引擎{{ $av['engine'] ?? 'N/A' }}
掃描檔案數{{ number_format($av['files_scanned'] ?? 0) }}
掃描目錄數{{ number_format($av['dirs_scanned'] ?? 0) }}
發現威脅{{ $av['infected'] ?? 0 }} 個
@if(!empty($av['threats']))

威脅清單

@foreach($av['threats'] as $t) @endforeach
檔案路徑病毒名稱
{{ $t['file'] ?? '' }}{{ $t['virus'] ?? '' }}
@else

✔ 未發現任何威脅。

@endif @endif @php $backups = collect($reportData['backup'] ?? []); @endphp @if($backups->isNotEmpty())

23. 備份狀態

@foreach($backups as $bk) @php $bkHours = $bk['last_backup_hours'] ?? -1; if (!($bk['dir_found'] ?? false)) { $bkStatus = '未找到目錄'; $bkClass = 'fail'; } elseif ($bkHours < 0) { $bkStatus = '未偵測到備份'; $bkClass = 'warn'; } elseif ($bkHours <= 25) { $bkStatus = '正常'; $bkClass = 'pass'; } else { $bkStatus = intval($bkHours/24) . ' 天前'; $bkClass = 'fail'; } @endphp @endforeach
類型腳本排程備份目錄最後備份時間24h 檔案目錄大小狀態
{{ $bk['type'] ?? '' }} {!! ($bk['script_found'] ?? false) ? '' : '' !!} {!! ($bk['in_cron'] ?? false) ? '' : '' !!} {{ $bk['dir_path'] ?? '—' }} {{ $bk['last_backup'] ?? '—' }} {{ $bk['files_24h'] ?? 0 }} {{ $bk['size'] ?? '—' }} {{ $bkStatus }}
@endif @php $li = $reportData['log_integrity'] ?? null; @endphp @if($li)

24. Log 完整性檢查

檢查檔案數 正常 新增 疑似異動 檢查時間
{{ $li['checked'] ?? 0 }} {{ $li['clean'] ?? 0 }} {{ $li['new_files'] ?? 0 }} {{ $li['tampered'] ?? 0 }} {{ $li['checked_at'] ?? '—' }}
@if(!empty($li['categories']))

各類別統計

@foreach($li['categories'] as $cat) @endforeach
類別檢查正常新增異動
{{ $cat['name'] ?? '—' }} {{ $cat['checked'] ?? 0 }} {{ $cat['clean'] ?? 0 }} {{ ($cat['new_files'] ?? 0) ?: '—' }} {{ ($cat['tampered'] ?? 0) > 0 ? $cat['tampered'] : '—' }}
@endif @if(!empty($li['tampered_files']))

疑似異動的 Log 檔案

@foreach($li['tampered_files'] as $tf) @endforeach
{{ $tf }}

若為正常輪替造成,可刪除 /opt/host-agent/.log_hashes 重建基準。

@endif @endif @if(!empty($sbomData)) @php $sbomTypes = [ 'apt' => ['label' => 'APT 套件', 'pkgs' => $sbomData['apt'] ?? []], 'pip' => ['label' => 'Python (pip)', 'pkgs' => $sbomData['pip'] ?? []], 'npm' => ['label' => 'Node.js (npm)', 'pkgs' => $sbomData['npm'] ?? []], 'composer' => ['label' => 'PHP (Composer)', 'pkgs' => $sbomData['composer'] ?? []], 'winget' => ['label' => 'Windows (winget)', 'pkgs' => $sbomData['winget'] ?? []], ]; $totalCount = array_sum(array_map(fn($t) => count($t['pkgs']), $sbomTypes)); @endphp

25. SBOM 軟體清單(Software Bill of Materials)

收集時間:{{ $sbomCollectedAt ?? 'N/A' }} 共 {{ $totalCount }} 個套件

@foreach($sbomTypes as $typeKey => $t) @if(count($t['pkgs']) > 0)

{{ $t['label'] }}({{ count($t['pkgs']) }} 個)

@foreach($t['pkgs'] as $pkg) @endforeach
名稱版本授權
{{ $pkg['name'] ?? '' }} {{ $pkg['version'] ?? '' }} {{ $pkg['license'] ?? '' }}
@endif @endforeach @endif