#!/bin/bash # Package Verification Check Script for SAW # Version: 1.0 # Date: 2026-04-02 # # This script checks the package verification configuration and verifies # that all installed packages are properly signed. # # Usage: sudo ./check-verification.sh # # SECURITY RATIONALE: # Regular verification of all installed packages ensures: # 1. No packages were tampered with after installation # 2. No malicious packages were added # 3. All packages are still properly signed # 4. Any compromised packages are detected early # # This should be run regularly (weekly/monthly) as part of security # monitoring and compliance verification. # # Reference: https://docs.fedoraproject.org/en-US/fedora-coreos/security-verification/ set -e # Configuration CA_KEY_PATH="/etc/pki/rpm-gpg/RPM-GPG-KEY-custom-ca" CRL_FILE="/etc/pki/ca-trust/source/anchors/crl.pem" LOG_FILE="/var/log/package-verification-check.log" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # Print functions log_info() { local timestamp=$(date '+%Y-%m-%d %H:%M:%S') echo -e "${GREEN}[$timestamp]${NC} ${BLUE}[INFO]${NC} $1" | tee -a "$LOG_FILE" } log_warning() { local timestamp=$(date '+%Y-%m-%d %H:%M:%S') echo -e "${YELLOW}[$timestamp]${NC} ${YELLOW}[WARNING]${NC} $1" | tee -a "$LOG_FILE" } log_error() { local timestamp=$(date '+%Y-%m-%d %H:%M:%S') echo -e "${RED}[$timestamp]${NC} ${RED}[ERROR]${NC} $1" | tee -a "$LOG_FILE" } # Check if running as root check_root() { if [ "$EUID" -ne 0 ]; then log_error "This script must be run as root" exit 1 fi } # Check CA certificate check_ca_certificate() { echo -e "${CYAN}1. CA Certificate Check${NC}" echo "==========================================" if [ -f "$CA_KEY_PATH" ]; then log_info "PASS: CA certificate installed" echo " Path: $CA_KEY_PATH" echo " Status: PRESENT" # Show certificate details openssl x509 -in "$CA_KEY_PATH" -noout -subject -issuer -dates 2>/dev/null | sed 's/^/ /' else log_error "FAIL: CA certificate not found" echo " Path: $CA_KEY_PATH" echo " Status: MISSING" echo " Action: Copy CA certificate to $CA_KEY_PATH" fi echo "" } # Check DNF configuration check_dnf_config() { echo -e "${CYAN}2. DNF Configuration Check${NC}" echo "==========================================" if [ ! -f /etc/dnf/dnf.conf ]; then log_error "FAIL: DNF configuration not found" echo " Status: FILE NOT FOUND" echo " Action: Create /etc/dnf/dnf.conf" echo "" return fi # Check gpgcheck if grep -q "^gpgcheck=1" /etc/dnf/dnf.conf; then log_info "PASS: Package GPG check enabled" echo " Status: ENABLED" else log_error "FAIL: Package GPG check not enabled" echo " Status: DISABLED" echo " Action: Add 'gpgcheck=1' to /etc/dnf/dnf.conf" fi # Check repo_gpgcheck if grep -q "^repo_gpgcheck=1" /etc/dnf/dnf.conf; then log_info "PASS: Repository GPG check enabled" echo " Status: ENABLED" else log_error "FAIL: Repository GPG check not enabled" echo " Status: DISABLED" echo " Action: Add 'repo_gpgcheck=1' to /etc/dnf/dnf.conf" fi echo "" } # Check RPM database check_rpm_database() { echo -e "${CYAN}3. RPM Database Check${NC}" echo "==========================================" # Check if CA key is imported if rpm -q gpg-pubkey 2>/dev/null | grep -q "$(basename $CA_KEY_PATH)"; then log_info "PASS: CA key imported into RPM database" echo " Status: IMPORTED" else log_warning "WARNING: CA key not imported into RPM database" echo " Status: NOT IMPORTED" echo " Action: Run 'rpm --import $CA_KEY_PATH'" fi echo "" } # Check audit script check_audit_script() { echo -e "${CYAN}4. Audit Script Check${NC}" echo "==========================================" if [ -f /usr/local/bin/verify-package.sh ]; then log_info "PASS: Package verification script exists" echo " Path: /usr/local/bin/verify-package.sh" echo " Status: PRESENT" if [ -x /usr/local/bin/verify-package.sh ]; then log_info "PASS: Script is executable" echo " Status: EXECUTABLE" else log_warning "WARNING: Script is not executable" echo " Status: NOT EXECUTABLE" echo " Action: Run 'chmod +x /usr/local/bin/verify-package.sh'" fi else log_warning "WARNING: Package verification script not found" echo " Status: NOT FOUND" echo " Action: Run the lockdown script to create the script" fi echo "" } # Check CRL file check_crl() { echo -e "${CYAN}5. CRL Check${NC}" echo "==========================================" if [ -f "$CRL_FILE" ]; then log_info "PASS: CRL file exists" echo " Path: $CRL_FILE" echo " Size: $(du -h "$CRL_FILE" | cut -f1)" # Check if CRL is valid if openssl crl -in "$CRL_FILE" -noout 2>/dev/null; then log_info "PASS: CRL is valid" echo " Status: VALID" # Show CRL dates openssl crl -in "$CRL_FILE" -noout -text 2>/dev/null | grep -E "(Last Update|Next Update):" | sed 's/^/ /' else log_error "FAIL: CRL is invalid" echo " Status: INVALID" fi else log_warning "WARNING: CRL file not found" echo " Path: $CRL_FILE" echo " Status: NOT FOUND" echo " Action: Run daily-crl-update.sh to download CRL" fi echo "" } # Check firewall rules check_firewall() { echo -e "${CYAN}6. Firewall Check${NC}" echo "==========================================" if command -v firewall-cmd &> /dev/null; then if firewall-cmd --state 2>/dev/null | grep -q "running"; then log_info "PASS: Firewall is running" echo " Status: RUNNING" # Show active rules echo " Active Zones:" firewall-cmd --list-zones 2>/dev/null | sed 's/^/ /' echo " Active Services:" firewall-cmd --list-services 2>/dev/null | sed 's/^/ /' else log_warning "WARNING: Firewall is not running" echo " Status: NOT RUNNING" fi else log_warning "WARNING: Firewall command not found" echo " Status: COMMAND NOT FOUND" fi echo "" } # Check SELinux check_selinux() { echo -e "${CYAN}7. SELinux Check${NC}" echo "==========================================" local selinux_status=$(sestatus 2>/dev/null || echo "SELinux not available") if echo "$selinux_status" | grep -q "Current mode: enforcing"; then log_info "PASS: SELinux is enforcing" echo " Status: ENFORCING" else log_warning "WARNING: SELinux is not enforcing" echo " Status: $(echo "$selinux_status" | grep "Current mode" | awk '{print $3}')" fi echo "" } # Check auditd check_auditd() { echo -e "${CYAN}8. Auditd Check${NC}" echo "==========================================" if systemctl is-active auditd >/dev/null 2>&1; then log_info "PASS: Auditd is running" echo " Status: RUNNING" else log_warning "WARNING: Auditd is not running" echo " Status: NOT RUNNING" fi echo "" } # Check for unsigned packages check_unsigned_packages() { echo -e "${CYAN}9. Unsigned Packages Check${NC}" echo "==========================================" local unsigned_count=0 local total_count=0 # Get list of installed packages while IFS= read -r pkg; do # Check if package has signature if ! rpm -q "$pkg" --queryformat='%{SIGPGP:pgpsig}\n' 2>/dev/null | grep -q "0x"; then log_warning "WARNING: Package has no signature: $pkg" ((unsigned_count++)) fi ((total_count++)) done < <(rpm -qa --queryformat='%{NAME}\n' 2>/dev/null | head -100) echo " Total packages checked: $total_count" echo " Unsigned packages found: $unsigned_count" echo "" } # Generate summary generate_summary() { echo "" echo "==========================================" echo " Package Verification Summary" echo " Date: $(date '+%Y-%m-%d %H:%M:%S')" echo " Hostname: $(hostname)" echo "==========================================" echo "" } # Main execution main() { echo "" echo "==========================================" echo " Package Verification Check" echo " Fedora Kinoite SAW" echo " Version: 1.0" echo "==========================================" echo "" check_root check_ca_certificate check_dnf_config check_rpm_database check_audit_script check_crl check_firewall check_selinux check_auditd check_unsigned_packages generate_summary echo "" echo "==========================================" echo " Check Complete!" echo "==========================================" echo "" echo "Recommendations:" echo "- Review any WARNING or ERROR items" echo "- Run this script weekly for critical systems" echo "- Run this script monthly for standard systems" echo "- Keep CA certificates secure" echo "- Regularly update CRL" echo "" } # Run main function main "$@"