User Tools

Site Tools


pages:scripts:chage-omfg

chage-omfg

#!/bin/bash

## -------------------------------------------------------------------------------------------------------
## check_password_age.sh
## -------------------------------------------------------------------------------------------------------
##
## Programmbeschreibung:
## Skript um das Alter des Passworts von root zu ermitteln und eine E-Mail abzusetzen falls das Alter
## einen konfigurierten Wert überschreitet.

## -------------------------------------------------------------------------------------------------------
## Initialisierung
## -------------------------------------------------------------------------------------------------------

# Debugging Option
# set -x

# /etc/profile sourcen
source /etc/profile

# Systemsprache explizit setzen um zu erzwingen, dass die Ausgabe auf Englisch erfolgt.
export LANG="en_US.UTF-8"


## -------------------------------------------------------------------------------------------------------
## Konfiguration des Skripts
## -------------------------------------------------------------------------------------------------------

MAXPASSWORDAGE=279;                                     # Maximales Alter des root-Passworts in Tagen

# Pfad zur Userliste
USERLIST="";                                            # Nicht editieren
PATHTOUSERLIST="/root/scripts/chage/data/";             # Pfad zur Datei, die die User zur Ueberpruefung beinhaltet
USERLISTFILE="users.txt";                               # Dateiname der Datei, die die Userliste enthaelt

# Mailversand
MAILSENDER="email@domain.com";                          # Absenderadresse
MAILRECEIVER="email@localhost";                         # Empfaengeradresse
SENDMAILIFNOOP="yes";                                   # Soll eine Mail gesendet werden wenn kein Fehler auftrat (yes|no)
SENDMAILIFERROR="yes";                                  # Soll eine Mail gesendet werden wenn ein Fehler aufgetreten ist (yes|no)
SENDMAILIFUPDATE="yes";                                 # Soll eine Mail gesendet werden wenn Updates von Passwoertern ausstehen (yes|no)

# Logging
MYNAME=$(basename $0);                                  # Dateiname des Scripts (nicht editieren)
LOGFILEPATH="/root/scripts/chage/log/";                 # Pfad zum skripteigenen Logfile
LOGFILENAME=$(hostname -f)"-checkpasswordage.log";      # Dateiname des skripteigenen Logfile
LOGFILE=${LOGFILEPATH}${LOGFILENAME};                   # Nicht editieren
LOGVERBOSITY="3";                                       # Standard-Loglevel [0 - 4]
SILENT_LVL="0";                                         # Definiert Silent (nicht editieren)
ERR_LVL="1";                                            # Definiert Loglevel von Error (nicht editieren)
WRN_LVL="2";                                            # Definiert Loglevel von Warn (nicht editieren)
INF_LVL="3";                                            # Definiert Loglevel von Info (nicht editieren)
DBG_LVL="4";                                            # Definiert Loglevel von Debug (nicht editieren)


## -------------------------------------------------------------------------------------------------------
## Strings
## -------------------------------------------------------------------------------------------------------

WORKLIST="";                                            # Nicht editieren
UPDATELIST="";                                          # Nicht editieren
ERRORSTATUSSTRING="";                                   # Nicht editieren
MYHOSTNAME=$(hostname -f);                              # Der Hostname des Systems auf dem das Skript laeuft (nicht editieren)
SUBJECTSTATENOOP="[NOOP]";                              # Mail-Subject-Indikator fuer einen erfolgreichen Lauf ohne Handlungsbedarf.
SUBJECTSTATEERROR="[ERROR]";                            # Mail-Subject-Indikator fuer einen Lauf bei dem Fehler aufgetreten sind.
SUBJECTSTATEUPDATE="[PENDING-PASSWORD-UPDATE]";         # Mail-Subject-Indikator fuer Useraccounts die einen Passwortwechsel benötigen.
MAILBODY="";


## -------------------------------------------------------------------------------------------------------
## Funktionen
## -------------------------------------------------------------------------------------------------------

# Ein formatiertes Datum bauen
function makeadate ()
{
        local l_FORMATTEDDATE="";
        l_FORMATTEDDATE=$(date +"%Y-%m-%d %H:%M:%S");
        echo "$l_FORMATTEDDATE";
}

# Die Userliste aus einer Datei auslesen und den Inhalt in ein Array befuellen, womit dann die WORKLIST befuellt wird
function readUserList ()
{
        local l_FULLPATHTOUSERLIST="";
        l_FULLPATHTOUSERLIST="${PATHTOUSERLIST}${USERLISTFILE}";
        USERLIST=$(awk '{print $1}' $l_FULLPATHTOUSERLIST);
}


# Minimales Logging und Error-Handling
function notify () { log $SILENT_LVL "NOTE: $1"; }      # Wird immer ausgegeben
function error ()
{
        log $ERR_LVL "ERROR: $1";
}
function warn () { log $WRN_LVL "WARNING: $1"; }
function inf () { log $INF_LVL "INFO: $1"; }            # "info" ist ein Shell-Kommando
function debug () { log $DBG_LVL "DEBUG: $1"; }
function log ()
{
        local l_LOGDATE="";
        l_LOGDATE=$(makeadate);
        if [ $LOGVERBOSITY -ge $1 ]
        then
                # Ins Logfile schreiben
                echo -e "${l_LOGDATE} - $2" >> $LOGFILE;

                # An das Syslog uebergeben
                logger -t "${MYNAME}" "${2}";

                #Den Error-String erweitern
                if [ $1 = $ERR_LVL ]
                then
                        ERRORSTATUSSTRING+="  $2\n";
                fi
        fi

        # Die Meldung an STDOUT ausgeben
        echo "$2";
}

# Funktion um zu testen ob es den User gibt.
# Existierende User werden der WORKLIST hinzugefuegt.
# Nicht existierende User oder mehrfach vorkommende User loesen einen Fehler aus.
function initialtest ()
{
        # debug "initialtest (): Teste User: ${1}";

        local l_TESTCOUNT=$(grep -c "^${1}:" /etc/shadow);

        # debug "initialtest (): TESTCOUNT: ${l_TESTCOUNT}";

        if [ ${l_TESTCOUNT} -ne 1 ]
        then
                if [ ${l_TESTCOUNT} = 0 ]
                then
                        error "initialtest (): User ${1} existiert nicht.";
                else
                        error "initialtest (): User ${1} kommt ${l_TESTCOUNT} mal vor.";
                fi
        else
                # debug "initialtest (): User ${1} gefunden und ${l_TESTCOUNT} mal vorhanden.";
                inf "initialtest (): User ${1} existiert.";
                inf "Fuege User ${1} der WORKLIST hinzu.";
                WORKLIST+=" "${i};
        fi
}


# Funktion um das Alter der Userpasswoerter zu ueberpruefen
function checkPasswordAge ()
{
        # debug "checkPasswordAge (): Ermittle Passwortalter von User: ${1}";

        # init
        local l_ITEMARRAY="";
        local l_PARSESTRING="";
        local l_COUNTERVAR=0;
        local l_ITEMARRAY="";
        local l_LASTCHANGEOFPASSWORD="";
        local l_TODAY="";
        local l_DIFFERENCE="";

        # Den Eintrag fuer den uebergebenen USER aus der /etc/shadow auslesen
        l_PARSESTRING=$(grep "^$1:" /etc/shadow);
        # debug "checkPasswordAge (): ermittelter String: ${l_PARSESTRING}";

        # Den String von Asterisks saeubern
        l_PARSESTRING=$(echo "${l_PARSESTRING}" | sed 's/\*/ASTERISK/g');
        # debug "l_PARSESTRING nach SED: ${l_PARSESTRING}";

        # Die Textzeile aus /etc/shadow fuer das Array aufsplitten
        l_ARRAYPREPARE=$(echo "${l_PARSESTRING}" | tr ":" "\n");
        # debug "l_ARRAYPREPARE: ${l_ARRAYPREPARE}";

        # Das Array befuellen
                # 0 = Username
                # 1 = Passwort-hash
                # 2 = Alter des Passworts in Tagen seit 01.01.1970
        l_ITEMARRAY=($l_ARRAYPREPARE);
        # debug "[0]=${l_ITEMARRAY[0]}";
        # debug "[1]=${l_ITEMARRAY[1]}";
        # debug "[2]=${l_ITEMARRAY[2]}";

        # Timestamp der letzten Passwortaenderung
        l_LASTCHANGEOFPASSWORD=${l_ITEMARRAY[2]};
        # debug "checkPasswordAge (): Timestamp der letzen Passwortaenderung: ${l_LASTCHANGEOFPASSWORD}.";

        # Timestamp fuer heute erzeugen
        l_TODAY=$(($(date --utc --date "" +%s)/86400));
        # debug "checkPasswordAge (): Timestamp von heute: ${l_TODAY}.";

        # Berechnen der Differenz zwischen den Timestamps der letzten Passwortaenderung und heute
        l_DIFFERENCE=$((l_TODAY-l_LASTCHANGEOFPASSWORD));
        # inf "checkPasswordAge (): Die Differenz zwischen den Timestamps der letzen Passwortaenderung und heute betraegt ${l_DIFFERENCE} Tage.";

        echo "${l_DIFFERENCE}";
}

function sendAlertMail ()
{
# Test ob eine Mail gesendet werden soll
if [ "${SENDMAILIFNOOP}" == "yes" ] || [ "${SENDMAILIFERROR}" == "yes" ] ||  [ "${SENDMAILIFUPDATE}" == "yes" ]
then
        notify "Mailen des Status vom ${SCRIPTSTARTDATE} gestartet.";
        inf "Konfiguration:";
        inf " * Mail bei NOOP: ${SENDMAILIFNOOP}";
        inf " * Mail bei Fehler: ${SENDMAILIFERROR}";
        inf " * Mail bei Updates: ${SENDMAILIFUPDATE}";

        local l_SUBJECTDATE=$SCRIPTSTARTDATE;
        local l_MAILSUBJECT="";
        local l_MAILBODY="";


        # Den Anfang des Betreff mit Hostname und Datum generieren.
        l_MAILSUBJECT="[${MYHOSTNAME}]: ${l_SUBJECTDATE} - ";

        # Den Status des Programmlaufs an den Betreff anhaengen.
        if [ "$ERRORSTATUSSTRING" = "" ]
        then
                # Wenn es keinen Fehler gab
                if [ "$UPDATELIST" = "" ]
                then
                        # Wenn keine Updates durchzufuehren sind (NOOP)
                        debug "sendAlertMail (): Es sind keine Updates auszufuehren, Subject um NOOP erweitert.";
                        l_MAILSUBJECT+="${SUBJECTSTATENOOP}";
                else
                        # Es liegen Userpasswoerter vor, die geupdated werden muessen (UPDATE)
                        debug "sendAlertMail (): Es liegen Updates vor, Subject um Update erweitert.";
                        l_MAILSUBJECT+="${SUBJECTSTATEUPDATE}"
                fi

        else
                # Es sind Fehler aufgetreten (ERROR)
                debug "sendAlertmail (): Es liegen Fehler vor, Subject um ERROR erweitert.";
                l_MAILSUBJECT+="${SUBJECTSTATEERROR}"
        fi

        # Bauen des Mail-Bodies abhaengig vom Status
        if [ "$ERRORSTATUSSTRING" = "" ]
        then
                # Es sind keine Fehler aufgetreten
                if [ "$UPDATELIST" =  "" ]
                then
                        # Wenn keine Updates durchzufuehren sind (NOOP)
                        debug "sendAlertMail (): Es sind keine Updates auszufuehren, NOOP-Body generieren.";
                        l_MAILBODY+="Beim Lauf des Skripts ${MYNAME} auf ${MYHOSTNAME} wurde keine Operation ausgefuehrt.\n";
                        l_MAILBODY+="\n";
                        l_MAILBODY+="==========================================================================================\n"
                        l_MAILBODY+="Das Alter des Passworts aller ueberprueften User ist unterhalb des Ablauflimits\n";
                        l_MAILBODY+="von ${MAXPASSWORDAGE} Tagen.\n";
                        l_MAILBODY+="==========================================================================================\n"
                else
                        # Es liegen Userpasswoerter vor, die geupdated werden muessen (UPDATE)
                        debug "sendAlertMail (): Es liegen Updates vor, UPDATE-Body generieren.";
                        l_MAILBODY+="Beim Lauf des Skripts ${MYNAME} auf ${MYHOSTNAME} wurden folgende User gefunden,\n";
                        l_MAILBODY+="deren Passwort abgelaufen ist.\n";
                        l_MAILBODY+="\n";
                        l_MAILBODY+="==========================================================================================\n";
                        for i in $UPDATELIST; do
                                l_MAILBODY+="${i}\n";
                        done;
                        l_MAILBODY+="==========================================================================================\n";
                fi

        else
                # Es sind Fehler aufgetreten (ERROR)
                debug "sendAlertMail (): Es sind Fehler aufgetreten, ERROR-Body generieren.";
                l_MAILBODY+="Beim Lauf des Skripts ${MYNAME} auf ${MYHOSTNAME} traten folgende Fehler auf:\n";
                l_MAILBODY+="\n";
                l_MAILBODY+="==========================================================================================\n";
                l_MAILBODY+="${ERRORSTATUSSTRING}";
                l_MAILBODY+="==========================================================================================\n";
        fi


        # Senden der E-Mail

        echo -e "${l_MAILBODY}" | mailx -s "${l_MAILSUBJECT}" -r $MAILSENDER $MAILRECEIVER && inf "Die Email an ${MAILRECEIVER} wurde versendet." || error "Die Email an ${MAILRECEIVER} konnte nicht versendet werden."

        notify "Mailen des Status der Passwortalterueberpruefung vom ${SCRIPTSTARTDATE} beendet."

fi
}

## -------------------------------------------------------------------------------------------------------
## Main
## -------------------------------------------------------------------------------------------------------

# Startup Info
SCRIPTSTARTDATE=$(makeadate);
notify "**************************************************************************************************";
notify "${SCRIPTSTARTDATE} - ${MYHOSTNAME}: ${MYNAME} gestartet."
notify "**************************************************************************************************";

# Die Userliste in USERLIST einlesen
readUserList;

# Initialer Test ob mehr als eine Trefferzeile von grep fuer einen User zurueckgeliefert wurde oder ob ein
# User gar nicht existiert.
# Wenn ein User existiert, wird er der WORKLIST hinzugefuegt.
inf "Initiale Tests und Befuellung der WORKLIST.";
for i in $USERLIST; do
        initialtest $i;
done;

# Wenn keine Fehlerkondition vorliegt wird das Alter des Passworts, der in der WORKLIST gelisteten User, ueberprueft. Wenn das Alter ueber der erlaubten
# Grenze ($MAXPASSWORDAGE) liegt, wird der User der UPDATELIST hinzugefuegt.
if [ "${ERRORSTATUSSTRING}" == "" ]
then
        inf "Die WORKLIST ist: ${WORKLIST}";

        # Aufruf der Funktion um das Alter der Passwoerter der einzelnen User aus USERLIST zu pruefen.
        inf "Abarbeitung der WORKLIST und ermitteln des Passwortalters.";
        for a in $WORKLIST; do
                USERPASSWORDAGE=$(checkPasswordAge $a);
                if [ "$USERPASSWORDAGE" -gt $MAXPASSWORDAGE ]
                then
                        # Wenn das Passwort abgelaufen ist
                        warn "Das Passwort von User $a ist $USERPASSWORDAGE Tage alt und ueber dem maximalen Passwortalter von $MAXPASSWORDAGE Tagen.";
                        UPDATELIST+=" "${a};
                else
                        # Wenn das Passwort nicht abgelaufen ist
                        inf "Das Passwort von User $a ist $USERPASSWORDAGE Tage alt und unter dem maximalen Passwortalter von $MAXPASSWORDAGE Tagen.";
                fi
        done;
fi

# Versenden der Mail
sendAlertMail;

# Skriptende Info
notify "**************************************************************************************************";
notify "$(makeadate) - ${MYHOSTNAME}: ${MYNAME} beendet."
notify "**************************************************************************************************\n\n";

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
pages/scripts/chage-omfg.txt · Last modified: 2022/12/31 00:39 by Heiko Mischer