Under Construction

Schritt 5: Setzen von PermitRootLogin auf no

Als nächstes soll das Setzen von PermitRootLogin auf den Wert „no“ implementiert werden. Bevor wir dies implementieren, wenden wir aber schon einmal die Regel aus custom/sshd.xml auf das System an:

/etc/security/aixpert # aixpert -f custom/sshd.xml
Processedrules=1        Passedrules=1   PrereqFailedrules=0     Failedrules=0   Level=TEST
        Input file=custom/sshd.xml
/etc/security/aixpert #

Laut der Ausgabe wurde die Regel erfolgreich umgesetzt (Passedrules=1)! Eine Überprüfung zeigt aber das dies natürlich nicht der Fall ist (Failedrules=1), schließlich haben wir die Umsetzung ja noch nicht implementiert:

/etc/security/aixpert # aixpert -c
Processedrules=1        Passedrules=0   Failedrules=1   Level=TEST
        Input file=/etc/security/aixpert/core/appliedaixpert.xml
/etc/security/aixpert #

Wir erweitern unser Skript und fügen die folgende Schleife am Ende des Skripts hinzu:

firstOccurrence=true
while read -r line
do
        case "$line" in
        PermitRootLogin*)
                if $firstOccurrence
                then
                        print "PermitRootLogin no"
                        firstOccurrence=false
                fi
                ;;
        *)
                print $line ;;
        esac
done </etc/ssh/sshd_config >/etc/ssh/sshd_config.new
$firstOccurrence && print "PermitRootLogin no" >>/etc/ssh/sshd_config.new
cp /etc/ssh/sshd_config.new /etc/ssh/sshd_config
rm /etc/ssh/sshd_config.new

Die Schleife liest /etc/ssh/sshd_config Zeile für Zeile ein. Falls eine Zeile mit PermitRootLogin beginnt, wird diese durch „PermitRootLogin no“ ersetzt (aber nur beim ersten Vorkommen). Für alle anderen Zeilen werden diese einfach übernommen. Die Zeilen werden in die Datei /etc/ssh/sshd_config.new geschrieben. Für den Fall das es keine Zeile mit PermitRootLogin gab, wird die Zeile „PermitRootLogin no“ einfach an das Ende von /etc/ssh/sshd_config.new angefügt. Und schließlich wird /etc/ssh/sshd_config.new nach /etc/ssh/sshd_config kopiert und die Zwischendatei gelöscht.

Hinweis: Die Schleife ist als erster Entwurf zu sehen und berücksichtigt nicht alle in der Praxis vorkommenden Fälle. Z.B. könnten vor PermitRootLogin ein oder mehrere Leerzeichen oder Tabulatoren stehen, oder es könnten Match-Statements in der sshd_config verwendet worden sein. In dem Fall müsste sichergestellt werden, das „PermitRootLogin no“ vor den Match-Statements steht. Und es gibt sicher weitere Spezialfälle die zu berücksichtigen sind.

Insgesamt ergibt sich dann die folgende Version des Skripts:

# cat /etc/security/aixpert/bin/local_chsshdconf
#! /bin/ksh

export PATH=/usr/bin:/usr/sbin:$PATH

# Initialize variables AIXPERT_FIFO, LOG, REPORT, SCPTDIR and UNDOXML
. /etc/security/aixpert/bin/initialize_variables

# Log output and errors to /etc/security/aixpert/log/aixpert.log
exec 1>>$LOG
exec 2>&1

# echo all the commands and the current time and date to the AIXpert log
set -x
date
echo $0 $@ AIXPERT_CHECK_REPORT=$AIXPERT_CHECK_REPORT BASE_REPT=$BASE_REPT DETAILED_REPT=$DETAILED_REPT

if [ $# -ne 0 ]
then
    echo "Usage : local_chsshdconf\n"
    exit 1
fi

# Check whether AIXPERT_CHECK_REPORT environment variable is set or not.
report=`echo $AIXPERT_CHECK_REPORT`
BrType=`echo $BASE_REPT`
DrType=`echo $DETAILED_REPT`

if [ "$report" = "1" ]
then
        ret=1

        permit=$( awk '$1 ~ /^PermitRootLogin$/ { print $2; }' /etc/ssh/sshd_config 2>/dev/null | tail -n 1 )
        case "${permit}" in
        [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]) ret=0 ;;
        esac

        if [ $ret = 1 ]
        then
                if [ "$BrType" = "1" ]
                then
                        echo "Base Compliance Report\n";
                        printf "local_chsshdconf: sshd attribute %s should have value %s, but it is %s now\n" PermitRootLogin no $permit >>$TMPREPT
                elif [ "$DrType" = "1" ]
                then
                        echo "Description Report\n";
                        printf "local_chsshdconf: sshd attribute %s should have value %s, but it is %s now\n" PermitRootLogin no $permit >>$TMPREPT
                else
                        printf "local_chsshdconf: sshd attribute %s should have value %s, but it is %s now\n" PermitRootLogin no $permit >>$REPORT
                        printf "local_chsshdconf: sshd attribute %s should have value %s, but it is %s now\n" PermitRootLogin no $permit >>$AIXPERT_FIFO
                fi
        fi

        exit $ret
fi

firstOccurrence=true
while read -r line
do
       case "$line" in
        PermitRootLogin*)
                if $firstOccurrence
                then
                        print "PermitRootLogin no"
                        firstOccurrence=false
                fi
                ;;
        *)
                print $line ;;
        esac
done </etc/ssh/sshd_config >/etc/ssh/sshd_config.new
$firstOccurrence && print "PermitRootLogin no" >>/etc/ssh/sshd_config.new
cp /etc/ssh/sshd_config.new /etc/ssh/sshd_config
rm /etc/ssh/sshd_config.new

exit 0

#

Ein Test-Lauf ist laut Ausgabe erneut erfolgreich:

/etc/security/aixpert # aixpert -f custom/sshd.xml
Processedrules=1        Passedrules=1   PrereqFailedrules=0     Failedrules=0   Level=TEST
        Input file=custom/sshd.xml
/etc/security/aixpert #

Wir starten eine Überprüfung und sehen das diese nun erfolgreich (Passedrules=1) war:

/etc/security/aixpert # aixpert -c
Processedrules=1        Passedrules=1   Failedrules=0   Level=TEST
        Input file=/etc/security/aixpert/core/appliedaixpert.xml
/etc/security/aixpert #

Eine kurze Überprüfung von /etc/ssh/sshd_config zeigt das der Wert von PermitRootLogin jetzt tatsächlich geändert wurde:

# grep -w PermitRootLogin /etc/ssh/sshd_config
PermitRootLogin no
#

Was in der obigen Schleife außerdem noch fehlt, ist eine Überprüfung auf Fehler! Tritt ein Fehler bei einem der Kommandos auf, sollte eine Meldung nach /etc/security/aixpert/log/aixpert.log geschrieben werden und das Skript sollte mit einem Exit-Status verschieden von 0 abbrechen. Für den Moment werden wir dies nicht implementieren.

Was noch fehlt ist die Unterstützung der Undo-Funktionalität. Damit beschäftigen wir uns im nachfolgenden Schritt.