Automate Linux Password Expiration for GB/T 22239 Compliance (90‑Day Policy)

This guide presents a complete, compliance‑ready solution for enforcing the GB/T 22239 (等保2.0) requirement that Linux user passwords be changed every 90 days, including a safe Bash script, audit logging, crontab scheduling, permission hardening, and evidence collection for security assessments.

Xiao Liu Lab
Xiao Liu Lab
Xiao Liu Lab
Automate Linux Password Expiration for GB/T 22239 Compliance (90‑Day Policy)

Overview

“The compliance requirement states: operating system user passwords must be forced to change within 90 days.”

Someone might write a simple script: chage -M 90 -d $(date) username Although it seems to meet the requirement, it introduces three major compliance pitfalls:

Including service accounts such as nobody or systemd in the password policy can cause system instability.

No operation logs or audit trail – evidence cannot be provided during assessment.

Script permissions are too open, allowing attackers to reverse‑engineer the operational logic.

We provide a “GB/T 22239 compliance version password‑policy automation solution” that not only satisfies the “90‑day validity” rule but also covers account classification, audit logging, permission control, and strong‑password linkage.

Optimization Principles – Align with GB/T 22239 “Secure Computing Environment” controls

Account Management : Process only real login users (UID ≥ 1000, login shell /bin/bash, exclude system accounts like nobody).

Operation Auditing : Record user, timestamp, old and new policies; support syslog reporting.

Permission Control : Script readable/writable only by root; crontab entries strictly limited.

Policy Linkage : Verify that /etc/login.defs enables strong passwords via pam_pwquality.

Compliant Hardened Script (with detailed comments)

#!/bin/bash
# Filename: password_policy_compliance.sh
# Revision: 2.0 (GB/T 22239 compliance version)
# Author: Security Team
# Description: Linux user password expiration management script meeting GB/T 22239 requirements

set -euo pipefail

# === Configuration ===
LOG_FILE="/var/log/password_policy.log"
SYSLOG_TAG="passwd-compliance"
SCRIPT_NAME=$(basename "$0")
SCRIPT_PATH=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)

# === Helper: Get real users ===
get_real_users() {
    awk -F: '
        $7 ~ /\/bin\/(ba)?sh$/ &&   # shell is bash or sh
        $3 >= 1000 &&               # UID ≥ 1000 (covers common distributions)
        $1 != "nobody" &&           # exclude nobody
        !/^(halt|sync|shutdown|mail|news|uucp|operator|games|gopher)/ {print $1}
    ' /etc/passwd
}

# === Permission check ===
if [[ $EUID -ne 0 ]]; then
    echo "Error: This script must be run as root." >&2
    exit 1
fi

# === Logging function ===
log_audit() {
    local msg="$1"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] $msg" >> "$LOG_FILE"
    logger -t "$SYSLOG_TAG" "$msg"
}

# === Ensure crontab entry ===
CRON_ENTRY="0 2 10 * * $SCRIPT_PATH/$SCRIPT_NAME >> $LOG_FILE 2>&1"
(crontab -l 2>/dev/null | grep -Fq "$CRON_ENTRY") || {
    (crontab -l 2>/dev/null; echo "$CRON_ENTRY") | crontab -
    log_audit "Automatically configured monthly password‑policy task"
}

# === Main logic: update password expiration for real users ===
log_audit "Starting password‑policy compliance check..."
while IFS= read -r user; do
    [[ -z "$user" ]] && continue
    current_max=$(chage -l "$user" 2>/dev/null | grep "Maximum number" | awk -F: '{print $2}' | tr -d ' ')
    if [[ "$current_max" != "90" ]]; then
        chage -M 90 -d "$(date +%Y-%m-%d)" "$user"
        log_audit "Updated user [$user] password expiration to 90 days (previous: ${current_max:-N/A})"
    fi
done < <(get_real_users)
log_audit "Password‑policy compliance check completed."

Deployment and Permission Hardening (must execute!)

# 1. Set script permissions (root only)
chmod 700 password_policy_compliance.sh
chown root:root password_policy_compliance.sh

# 2. Protect log file
touch /var/log/password_policy.log
chmod 600 /var/log/password_policy.log
chown root:root /var/log/password_policy.log

# 3. Verify syslog receives logs (GB/T 22239 requires 180‑day retention)
grep "passwd-compliance" /var/log/messages

Evidence to Provide During Assessment

Policy file: PASS_MAX_DAYS 90 in /etc/login.defs
Execution log: /var/log/password_policy.log (contains operation details)
System log: syslog entries in /var/log/messages
Cron job: output of crontab -l (proves automation)
Account list: script processes only real users, no system accounts

These five items can be directly used as evidence for the “Secure Computing Environment – Identity Authentication” control.

Advanced Recommendations (for Level‑3 compliance)

Enable strong password policy: ensure pam_pwquality.so is active in /etc/pam.d/system-auth
Integrate with bastion host: automatically sync expired‑password users to an audit system
Periodic verification: run monthly awk -F: '$5 ~ /90/ {print $1}' /etc/shadow to validate policy

Final Thoughts

Compliance is not a checkbox; it is a trusted baseline.
Even a tiny password‑policy script can become an anchor point of your security framework.
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Information Securitybashcompliance automation
Xiao Liu Lab
Written by

Xiao Liu Lab

An operations lab passionate about server tinkering 🔬 Sharing automation scripts, high-availability architecture, alert optimization, and incident reviews. Using technology to reduce overtime and experience to avoid major pitfalls. Follow me for easier, more reliable operations!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.