银河麒麟 V10 安全加固验证脚本(优化版)

#!/bin/bash

# 银河麒麟 V10 安全加固验证脚本(优化版)

# 运行方式: sudo ./kylin_security_test.sh

# 特点: 无 Emoji、POSIX 兼容、跳过不存在项、详细错误提示

LOG_FILE="/var/log/kylin_security_test.log"

exec > >(tee -a "$LOG_FILE") 2>&1

# 检查是否以 root 运行

if [ "$(id -u)" -ne 0 ]; then

    echo "[ERROR] 请使用 root 或 sudo 运行此脚本"

    exit 1

fi

echo "=============================================="

echo "[$(date)] 银河麒麟 V10 安全加固验证开始"

echo "=============================================="

PASS=0

FAIL=0

SKIP=0

# 安全日志函数(避免重定向问题)

log() {

    echo "[$(date +%T)] $*"

}

# 检查函数:兼容 sh/bash,避免 [[

check() {

    local desc="$1"

    shift

    if "$@" 2>/dev/null; then

        log "[OK] $desc"

        PASS=$((PASS + 1))

        return 0

    else

        log "[FAIL] $desc"

        FAIL=$((FAIL + 1))

        return 1

    fi

}

# 跳过函数

skip() {

    log "[SKIP] $*"

    SKIP=$((SKIP + 1))

}

# 1. SSH 禁止 root 远程登录

check "SSH 禁止 root 远程登录" grep -q "^PermitRootLogin no" /etc/ssh/sshd_config

# 2. opsadmin 用户及 sudo 权限

check "dqydy 用户存在" id dqydy >/dev/null 2>&1

if id dqydy >/dev/null 2>&1; then

    # 检查 sudoers.d 配置文件内容(避免 sudo -l 交互问题)

    if [ -f /etc/sudoers.d/dqydy ]; then

        if grep -q "dqydy ALL=(ALL:ALL) NOPASSWD:ALL" /etc/sudoers.d/dqydy 2>/dev/null; then

            log "[OK] dqydy 具备 sudo 权限 (NOPASSWD:ALL)"

            PASS=$((PASS + 1))

        else

            log "[FAIL] dqydy sudo 配置内容不符合预期"

            FAIL=$((FAIL + 1))

        fi

    else

        skip "dqydy sudo 配置文件不存在 (/etc/sudoers.d/dqydy)"

    fi

else

    skip "dqydy 用户不存在,跳过 sudo 权限检查"

fi

# 3. 三员账户存在性

for user in sysadmin secadmin auditadmin; do

    if id "$user" >/dev/null 2>&1; then

        log "[OK] 职能用户 $user 存在"

        PASS=$((PASS + 1))

    else

        log "[FAIL] 职能用户 $user 不存在"

        FAIL=$((FAIL + 1))

    fi

done

# 4. auditd 服务状态

if systemctl is-active --quiet auditd 2>/dev/null && systemctl is-enabled --quiet auditd 2>/dev/null; then

    log "[OK] auditd 服务已启用并运行"

    PASS=$((PASS + 1))

else

    log "[FAIL] auditd 服务未运行或未启用"

    FAIL=$((FAIL + 1))

fi

# 5. 日志文件权限检查(兼容银河麒麟路径)

LOG_FILES=(

    "/var/log/messages"

    "/var/log/secure"

    "/var/log/audit/audit.log"

)

for log in "${LOG_FILES[@]}"; do

    if [ -f "$log" ]; then

        perm=$(stat -c "%a" "$log" 2>/dev/null)

        if [ "$perm" = "640" ]; then

            log "[OK] $log 权限为 640"

            PASS=$((PASS + 1))

        else

            log "[FAIL] $log 权限应为 640 (当前: $perm)"

            FAIL=$((FAIL + 1))

        fi

    else

        skip "跳过 $log (文件不存在)"

    fi

done

# 6. auditadmin 属于 adm 组

if id auditadmin >/dev/null 2>&1; then

    if groups auditadmin | grep -qw "adm"; then

        log "[OK] auditadmin 属于 adm 组"

        PASS=$((PASS + 1))

    else

        log "[FAIL] auditadmin 未加入 adm 组"

        FAIL=$((FAIL + 1))

    fi

else

    skip "auditadmin 用户不存在,跳过组检查"

fi

# 7. auditadmin 可读取审计日志

if id auditadmin >/dev/null 2>&1 && [ -f /var/log/audit/audit.log ]; then

    if su - auditadmin -c "cat /var/log/audit/audit.log > /dev/null 2>&1" 2>/dev/null; then

        log "[OK] auditadmin 可读取审计日志"

        PASS=$((PASS + 1))

    else

        log "[FAIL] auditadmin 无权读取 /var/log/audit/audit.log"

        FAIL=$((FAIL + 1))

    fi

else

    skip "auditadmin 或审计日志不存在,跳过读取测试"

fi

# 8. 全局 HISTSIZE=0

if grep -q "^HISTSIZE=0" /etc/profile 2>/dev/null; then

    log "[OK] 全局 HISTSIZE=0 已设置"

    PASS=$((PASS + 1))

else

    log "[FAIL] /etc/profile 中未设置 HISTSIZE=0"

    FAIL=$((FAIL + 1))

fi

# 9. logrotate 配置

check "logrotate 设置为 weekly" grep -q "^weekly" /etc/logrotate.conf

check "logrotate rotate 28" grep -q "^rotate 28" /etc/logrotate.conf

# 10. sudoers.d 配置文件权限

for user in dqydy sysadmin secadmin auditadmin; do

    file="/etc/sudoers.d/$user"

    if [ -f "$file" ]; then

        perm=$(stat -c "%a" "$file" 2>/dev/null)

        if [ "$perm" = "440" ]; then

            log "[OK] $file 权限为 440"

            PASS=$((PASS + 1))

        else

            log "[FAIL] $file 权限应为 440 (当前: $perm)"

            FAIL=$((FAIL + 1))

        fi

    else

        skip "跳过 $file (不存在)"

    fi

done

# 结果汇总

echo "=============================================="

echo "验证完成!结果统计:"

echo "  [OK]    : $PASS 项"

echo "  [FAIL]  : $FAIL 项"

echo "  [SKIP]  : $SKIP 项"

echo "详细日志: $LOG_FILE"

echo "=============================================="

if [ $FAIL -eq 0 ]; then

    echo "[SUCCESS] 所有安全配置验证通过!"

    exit 0

else

    echo "[WARNING] 存在 $FAIL 项未通过,请检查日志定位问题"

    exit 1

fi