Pages

CIS SUSE Linux Compliance Script (Sections 1–7)

CIS SUSE Linux Compliance Script (Sections 1–7)

#!/bin/bash
# CIS SUSE Linux Compliance Script (Sections 1–7)
# Automated checks + manual flags
# -------------------------------
# Colors
# -------------------------------
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# -------------------------------
# Logging & Counters
# -------------------------------
REPORT="/var/log/cis_suse_report.log"
> $REPORT
PASS=0
FAIL=0
MANUAL=0
log_pass() { echo -e "${GREEN}[PASS]${NC} $1" | tee -a $REPORT; ((PASS++)); }
log_fail() { echo -e "${RED}[FAIL]${NC} $1" | tee -a $REPORT; ((FAIL++)); }
log_manual() { echo -e "${YELLOW}[MANUAL]${NC} $1" | tee -a $REPORT; ((MANUAL++)); }
# -------------------------------
# Helper Functions
# -------------------------------
check_file_perm() {
    local file=$1
    local perm=$2
    [ -e "$file" ] || { log_fail "$file does not exist"; return; }
    actual_perm=$(stat -c "%a" "$file")
    [ "$actual_perm" == "$perm" ] && log_pass "$file permissions ($perm) correct" || log_fail "$file permissions ($actual_perm) incorrect, should be $perm"
}
check_service_disabled() {
    local svc=$1
    systemctl is-enabled "$svc" &>/dev/null || { log_pass "$svc disabled"; return; }
    systemctl is-active "$svc" &>/dev/null && log_fail "$svc is enabled/active" || log_pass "$svc disabled"
}
check_package_installed() {
    local pkg=$1
    rpm -q "$pkg" &>/dev/null && log_pass "$pkg installed" || log_fail "$pkg not installed"
}
# -------------------------------
# SECTION 1 – Initial Setup
# -------------------------------
echo -e "${YELLOW}==== SECTION 1 – Initial Setup ====${NC}" | tee -a $REPORT
log_manual "Check SUSE registration and subscription status (SUSEConnect --status)"
# -------------------------------
# SECTION 2 – Services
# -------------------------------
echo -e "${YELLOW}==== SECTION 2 – Services ====${NC}" | tee -a $REPORT
services_to_disable=(
    autofs avahi-daemon dhcpd named dnsmasq smb nfs rpcbind rsync snmpd telnet tftp xinetd vsftpd apache2
)
for svc in "${services_to_disable[@]}"; do
    check_service_disabled "$svc"
done
systemctl is-enabled cron &>/dev/null && log_pass "cron enabled" || log_fail "cron disabled"
# -------------------------------
# SECTION 3 – Network
# -------------------------------
echo -e "${YELLOW}==== SECTION 3 – Network ====${NC}" | tee -a $REPORT
check_service_disabled "bluetooth"
nmcli radio wifi off &>/dev/null && log_pass "Wireless interfaces disabled" || log_manual "Check wireless interfaces manually"
sysctl_checks=(
    "net.ipv4.ip_forward=0"
    "net.ipv4.conf.all.send_redirects=0"
    "net.ipv4.conf.default.send_redirects=0"
    "net.ipv4.icmp_ignore_bogus_error_responses=1"
    "net.ipv4.icmp_echo_ignore_broadcasts=1"
    "net.ipv4.conf.all.accept_redirects=0"
    "net.ipv4.conf.default.accept_redirects=0"
    "net.ipv4.conf.all.secure_redirects=0"
    "net.ipv4.conf.default.secure_redirects=0"
    "net.ipv4.conf.all.rp_filter=1"
    "net.ipv4.conf.default.rp_filter=1"
    "net.ipv4.conf.all.accept_source_route=0"
    "net.ipv4.conf.default.accept_source_route=0"
    "net.ipv4.tcp_syncookies=1"
)
for param in "${sysctl_checks[@]}"; do
    key=$(echo $param | cut -d= -f1)
    val=$(echo $param | cut -d= -f2)
    current=$(sysctl -n "$key")
    [ "$current" == "$val" ] && log_pass "$key = $val" || log_fail "$key = $current, should be $val"
done
# -------------------------------
# SECTION 4 – Host-Based Firewall
# -------------------------------
echo -e "${YELLOW}==== SECTION 4 – Host-Based Firewall ====${NC}" | tee -a $REPORT
check_package_installed "firewalld"
systemctl is-enabled firewalld &>/dev/null && log_pass "firewalld enabled" || log_fail "firewalld disabled"
# -------------------------------
# SECTION 5 – Access Control
# -------------------------------
echo -e "${YELLOW}==== SECTION 5 – Access Control ====${NC}" | tee -a $REPORT
ssh_config="/etc/ssh/sshd_config"
check_file_perm "$ssh_config" "600"
grep -q "^PermitRootLogin no" "$ssh_config" && log_pass "SSH root login disabled" || log_fail "SSH root login not disabled"
check_package_installed "sudo"
log_manual "Verify pam_pwquality, password complexity, and PAM configuration"
awk -F: '($2!="x") {print $1}' /etc/passwd | grep -v '^$' && log_fail "Some accounts do not use shadow passwords" || log_pass "All accounts use shadowed passwords"
# -------------------------------
# SECTION 6 – Logging and Auditing
# -------------------------------
echo -e "${YELLOW}==== SECTION 6 – Logging and Auditing ====${NC}" | tee -a $REPORT
check_package_installed "audit"
systemctl is-enabled auditd &>/dev/null && log_pass "auditd enabled" || log_fail "auditd disabled"
systemctl is-enabled rsyslog &>/dev/null && log_pass "rsyslog enabled" || log_fail "rsyslog disabled"
check_package_installed "aide"
log_manual "Ensure AIDE database initialized and integrity checks are scheduled"
# -------------------------------
# SECTION 7 – System Maintenance
# -------------------------------
echo -e "${YELLOW}==== SECTION 7 – System Maintenance ====${NC}" | tee -a $REPORT
declare -A files=(
    ["/etc/passwd"]="644"
    ["/etc/passwd-"]="644"
    ["/etc/group"]="644"
    ["/etc/group-"]="644"
    ["/etc/shadow"]="600"
    ["/etc/shadow-"]="600"
    ["/etc/gshadow"]="600"
    ["/etc/gshadow-"]="600"
    ["/etc/shells"]="644"
    ["/etc/security/opasswd"]="600"
)
for file in "${!files[@]}"; do
    check_file_perm "$file" "${files[$file]}"
done
find / -xdev -type f -perm -002 ! -exec stat -c "%n" {} \; 2>/dev/null | grep -vE "^/proc|^/sys|^/dev" \
    && log_fail "World-writable files found" || log_pass "No world-writable files"
find / -xdev -type d -perm -002 ! -exec stat -c "%n" {} \; 2>/dev/null | grep -vE "^/proc|^/sys|^/dev" \
    && log_fail "World-writable directories found" || log_pass "No world-writable directories"
log_manual "Review SUID/SGID files: find / -xdev \\( -perm -4000 -o -perm -2000 \\) -type f"
awk -F: '($7!="/sbin/nologin" && $7!="/usr/sbin/nologin") {print $1":"$6}' /etc/passwd | while IFS=: read user dir; do
    [ -d "$dir" ] && log_pass "Home directory exists for $user" || log_fail "Home directory missing for $user"
done
echo -e "${YELLOW}==== CIS SUSE Linux Compliance Check Complete ====${NC}" | tee -a $REPORT
echo -e "${GREEN}PASS: $PASS${NC} | ${RED}FAIL: $FAIL${NC} | ${YELLOW}MANUAL: $MANUAL${NC}" | tee -a $REPORT

CIS SUSE Linux Auto-Remediation Script

CIS SUSE Linux Auto-Remediation:

#!/bin/bash
# =====================================================
# Enhanced Level 1 CIS SUSE Linux Auto-Remediation
# Full Auto-Remediation (Sections 1–7)
# Color-coded terminal output
# =====================================================
# -------------------------------
# Color Codes
# -------------------------------
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# -------------------------------
# Logging & Counters
# -------------------------------
REPORT="/var/log/cis_suse_auto_report.log"
> $REPORT
PASS=0; FAIL=0; REMEDIATED=0; MANUAL=0
log_pass() { echo -e "${GREEN}[PASS]${NC} $1" | tee -a $REPORT; ((PASS++)); }
log_fail() { echo -e "${RED}[FAIL]${NC} $1" | tee -a $REPORT; ((FAIL++)); }
log_manual() { echo -e "${YELLOW}[MANUAL]${NC} $1" | tee -a $REPORT; ((MANUAL++)); }
log_remediated() { echo -e "${GREEN}[REMEDIATED]${NC} $1" | tee -a $REPORT; ((REMEDIATED++)); }
# -------------------------------
# Helper Functions
# -------------------------------
check_file_perm() {
    file=$1
    perm=$2
    if [ -f "$file" ]; then
        actual_perm=$(stat -c "%a" "$file")
        if [ "$actual_perm" != "$perm" ]; then
            chmod "$perm" "$file" && log_remediated "Fixed permissions on $file to $perm" || log_fail "Failed to set permissions on $file"
        else
            log_pass "$file permissions correct ($perm)"
        fi
    else
        log_fail "$file not found"
    fi
}
disable_service() {
    svc=$1
    if systemctl list-unit-files | grep -q "^$svc"; then
        systemctl disable --now "$svc" && log_remediated "Disabled $svc" || log_fail "Failed to disable $svc"
    else
        log_pass "$svc service not installed or already disabled"
    fi
}
enable_service() {
    svc=$1
    systemctl enable --now "$svc" && log_remediated "Enabled $svc" || log_fail "Failed to enable $svc"
}
set_ssh_config() {
    param=$1
    value=$2
    SSH_CONFIG="/etc/ssh/sshd_config"
    if grep -q "^$param" "$SSH_CONFIG"; then
        sed -i "s/^$param.*/$param $value/" "$SSH_CONFIG" && log_remediated "SSH $param set to $value" || log_fail "Failed to set SSH $param"
    else
        echo "$param $value" >> "$SSH_CONFIG" && log_remediated "SSH $param added as $value"
    fi
}
set_pam_password_policy() {
    AUTH_FILE="/etc/security/pwquality.conf"
    sed -i '/^minlen/d' $AUTH_FILE
    sed -i '/^dcredit/d' $AUTH_FILE
    sed -i '/^ucredit/d' $AUTH_FILE
    sed -i '/^ocredit/d' $AUTH_FILE
    sed -i '/^lcredit/d' $AUTH_FILE
    echo "minlen = 14" >> $AUTH_FILE
    echo "dcredit = -1" >> $AUTH_FILE
    echo "ucredit = -1" >> $AUTH_FILE
    echo "ocredit = -1" >> $AUTH_FILE
    echo "lcredit = -1" >> $AUTH_FILE
    log_remediated "PAM password complexity set"
}
set_pam_lockout() {
    AUTH_FILE="/etc/pam.d/common-auth"
    if ! grep -q "pam_faillock.so" $AUTH_FILE; then
        sed -i '/auth\s\+required\s\+pam_unix.so/i auth required pam_faillock.so preauth silent deny=5 unlock_time=900' $AUTH_FILE
        sed -i '/auth\s\+required\s\+pam_unix.so/a auth [default=die] pam_faillock.so authfail deny=5 unlock_time=900' $AUTH_FILE
        sed -i '/account\s\+required\s\+pam_unix.so/i account required pam_faillock.so' $AUTH_FILE
        log_remediated "PAM account lockout configured"
    else
        log_pass "PAM faillock already configured"
    fi
}
# -------------------------------
# SECTION 1 – Initial Setup
# -------------------------------
echo -e "${YELLOW}==== SECTION 1 – Initial Setup ====${NC}" | tee -a $REPORT
log_manual "Verify SUSE version, kernel, and updates manually (cat /etc/os-release, uname -r, zypper list-updates)"
# -------------------------------
# SECTION 2 – Services
# -------------------------------
echo -e "${YELLOW}==== SECTION 2 – Services ====${NC}" | tee -a $REPORT
services_to_disable=(autofs avahi dhcpd named dnsmasq smb nfs vsftpd rpcbind rsync snmpd telnet tftp squid httpd xinetd ypbind cups)
for svc in "${services_to_disable[@]}"; do
    disable_service "$svc"
done
# -------------------------------
# SECTION 3 – Network
# -------------------------------
echo -e "${YELLOW}==== SECTION 3 – Network ====${NC}" | tee -a $REPORT
sysctl_params=(
    "net.ipv4.ip_forward=0"
    "net.ipv4.conf.all.send_redirects=0"
    "net.ipv4.conf.default.send_redirects=0"
    "net.ipv4.icmp_ignore_bogus_error_responses=1"
    "net.ipv4.icmp_echo_ignore_broadcasts=1"
    "net.ipv4.conf.all.accept_redirects=0"
    "net.ipv4.conf.default.accept_redirects=0"
    "net.ipv4.conf.all.secure_redirects=0"
    "net.ipv4.conf.default.secure_redirects=0"
    "net.ipv4.conf.all.rp_filter=1"
    "net.ipv4.conf.default.rp_filter=1"
    "net.ipv4.tcp_syncookies=1"
)
for p in "${sysctl_params[@]}"; do
    key=${p%=*}
    val=${p#*=}
    sysctl -w $key=$val >/dev/null 2>&1 && log_remediated "Sysctl $key set to $val" || log_fail "Failed $key=$val"
done
sysctl -p >/dev/null 2>&1
# -------------------------------
# SECTION 4 – Host-Based Firewall
# -------------------------------
echo -e "${YELLOW}==== SECTION 4 – Firewall ====${NC}" | tee -a $REPORT
enable_service "firewalld"
firewall-cmd --reload >/dev/null 2>&1 && log_remediated "Firewall reloaded" || log_fail "Failed to reload firewall"
# -------------------------------
# SECTION 5 – Access Control
# -------------------------------
echo -e "${YELLOW}==== SECTION 5 – Access Control ====${NC}" | tee -a $REPORT
# SSH hardening
set_ssh_config "PermitRootLogin" "no"
set_ssh_config "PasswordAuthentication" "no"
check_file_perm "/etc/ssh/sshd_config" "600"
systemctl restart sshd
# Sudo hardening
sed -i 's/^%wheel.*NOPASSWD/%wheel ALL=(ALL) ALL/' /etc/sudoers && log_remediated "Sudo password requirement enforced"
# PAM password policy & lockout
set_pam_password_policy
set_pam_lockout
# -------------------------------
# SECTION 6 – Logging & Auditing
# -------------------------------
echo -e "${YELLOW}==== SECTION 6 – Logging & Auditing ====${NC}" | tee -a $REPORT
enable_service "auditd"
auditctl -e 1 >/dev/null 2>&1
log_remediated "Auditd enabled and running"
# Default audit rules
cat <<EOF >/etc/audit/rules.d/cis.rules
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/gshadow -p wa -k identity
-w /etc/sudoers -p wa -k scope
-w /var/log/secure -p wa -k logins
EOF
augenrules --load && log_remediated "Audit rules loaded"
# -------------------------------
# SECTION 7 – System Maintenance
# -------------------------------
echo -e "${YELLOW}==== SECTION 7 – System Maintenance ====${NC}" | tee -a $REPORT
declare -A files=(
    ["/etc/passwd"]="644"
    ["/etc/shadow"]="600"
    ["/etc/group"]="644"
    ["/etc/gshadow"]="600"
)
for file in "${!files[@]}"; do
    check_file_perm "$file" "${files[$file]}"
done
# World-writable files
world_files=$(find / -xdev -type f -perm -2 2>/dev/null)
[ -n "$world_files" ] && log_fail "World-writable files found" || log_pass "No world-writable files"
log_manual "Review SUID/SGID files manually: find / -type f \( -perm -4000 -o -perm -2000 \) -exec ls -l {} \;"
# -------------------------------
# Final Summary
# -------------------------------
echo -e "${YELLOW}==== CIS SUSE Auto-Remediation Complete ====${NC}" | tee -a $REPORT
echo -e "${GREEN}PASS: $PASS${NC} | ${RED}FAIL: $FAIL${NC} | ${GREEN}REMEDIATED: $REMEDIATED${NC} | ${YELLOW}MANUAL: $MANUAL${NC}" | tee -a $REPORT