Two-Factor Authentication with OTP (Admin Guide)
The problem
Login to the head nodes of HPC systems is often just secured by simple (user-generated) passwords, which are also often identical for services like e-mail. A second login factor (2FA) is a second authentication factor independent of the password and using a completely different secret. Also, OTP passwords are only used once at each login and created on demand, valid for only minutes or seconds. This makes hacking these accounts difficult for attackers.
About OTP
OTP (one-time-passwords) compute password based on an initial secret (like a private key) and an algorithm. Passwords are computed iteratively, either on demand (at each login) or at specific intervals. The OTP Key is (from a security standpoint) extremely sensitive and must be guarded against theft.
On the server side, oath is needed:
oathtool.x86_64 : A command line tool for generating and validating OTPs
liboath.x86_64 : Library for OATH handling
pam_oath.x86_64 : A PAM module for pluggable login authentication for OATH
On the client-side, software for desktop and mobile devices exist:
The Idea
Just as with passwords, the generation and distribution of the OTP Key need to be secured. We assume that the user has a password set for the system to log into and use the first login of the user to set up the OTP Key for this user and give him the necessary information to log in again later (with password and OTP). Therefore, on the first login, the user is presented some information and then logged out again.
The Setup
After installing oathtool
, PAM
must be adapted:
/etc/pam.d/ssh
auth [success=2 default=ignore] pam_succeed_if.so uid = 0 # skip 2 lines for root auth [success=1 default=ignore] pam_succeed_if.so user notingroup otpusers # ignore users not yet in otpusers auth requisite pam_oath.so usersfile=/var/security/auth/users.oath window=20 # accept one of 20 consecutive keys (in case clocks of user and server are out of sync)
and /etc/ssh/sshd_config:
ChallengeResponseAuthentication yes PasswordAuthentication no UsePAM yes
On first login, a user is not yet a member of group otpusers and pam_oath.so is thus not run. The login environment then, through scripts in /etc/profile.d/
, generates the OTP Key for the user and puts him/her into the group otpusers and quits:
/etc/profile.d/create_secret.sh
####/bin/bash # RRZK, 2015-12-10 (CO) OATH_FILE="/var/security/auth/users.oath" OTPGROUP="otpusers" ME=$(/usr/bin/whoami) #ME=${PAM_USER} HOST=${HOSTNAME} RET=0 /usr/bin/id -Gn ${ME}|/bin/grep ${OTPGROUP} >/dev/null 2>&1 RET=$? if [ ! ${ME} = "root" ] && [ ${RET} -ne 0 ]; then # Disable CTRL-C trap '' 2 /bin/echo -e " Hello ${ME} I will generate a TOTP (time based) OATH Secret for you... " # generate secret /bin/echo "... generating secret" SECRET=$(/usr/bin/head -10 /dev/urandom | /usr/bin/sha512sum | /bin/cut -b 19-50) # generate base32 secret /bin/echo "... generating base32 secret" BASE32=$(/usr/bin/oathtool --totp -v ${SECRET}|/bin/grep 'Base32'|/bin/awk '{print $NF}') # generate qrcode /bin/echo "... generating qrcode" /usr/bin/qrencode -l H -v 1 --background=FFFFFF -o ${ME}_oath.png "otpauth://totp/${ME}@${HOST}?secret=${BASE32}" # insert secret in oath database /bin/echo "... adding secret to oath database" /bin/echo "... adding user to otpuser group" TMPFILE=$(/bin/mktemp ) || exit 1 /bin/echo -e "HOTP/T30/6\t${ME}\t-\t${SECRET}" > $TMPFILE /usr/bin/sudo -u root /usr/local/sbin/add_secret.sh ${TMPFILE} ${OTPGROUP} ${ME} /bin/rm -f TMPFILE /bin/echo "... finished" echo "Secret: ${SECRET} BASE32 Secret:${BASE32}" > ${ME}_oath.dat /bin/echo " Your Secret is: ${SECRET} Your BASE32 Secret is ${BASE32} Your QR-Code is: ${ME}_oath.png Enter your secret in your OTP Token (enter BASE32 without the trailing '=') or Display this file and scan it with your OTP Token APP. (X11Forward only) " /bin/echo "To display your QR-Code, press <d><ENTER>" read INPUT if [ "$INPUT" = "d" ]; then /usr/bin/display ${ME}_oath.png fi logout fi
The script /usr/local/sbin/add_secret.sh:
#/bin/bash # RRZK, 2015-12-10 (CO) OATH_FILE=/var/security/auth/users.oath TMPFILE=$1 OTPGROUP=$2 USER=$3 /bin/cat ${TMPFILE} >> ${OATH_FILE} /usr/sbin/usermod -a -G ${OTPGROUP} ${USER} exit 0
called per sudo(!), is then used to put the user in the group otpusers and save the OTP Key in the database file /var/security/auth/users.oath . Of course, an appropriate sudo rule has to be installed, too.
Finishing …
The script create_secret.sh puts the OTP Keys (text and image) into the home directory of the user:
- ${ME}_oath.dat
- ${ME}_oath.png
These files are later removed using cfengine.
Example
First Login
Hello test I will generate a TOTP (time based) OATH Secret for you... ... generating secret ... generating base32 secret ... generating qrcode ... adding secret to oath database ... adding user to otpuser group ... finished Your Secret is: c6cc87165150391e272194876ebd9ad4 Your BASE32 Secret is Y3GIOFSRKA4R4JZBSSDW5PM22Q====== Your QR-Code is: test_oath.png Enter your secret in your OTP Token (enter BASE32 without the trailing '=') or Display this file and scan it with your OTP Token APP. (X11Forward only) To display your QR-Code, press <d><ENTER>
Second Login
The login process then looks like this:
rpabel@soliton:~> ssh rpa@hermes.rrz.uni-koeln.de One-time password (OATH) for `rpa': Password: Last login: Thu Jul 9 14:07:55 2020 from soliton.rrz.uni-koeln.de [rpa@hermes ~]$
Remarks
- For HPC use, the oath.users should be identical for all login nodes. Put it on the /home parallel filesystem?
- The group otpusers is there to save just one bit of data (user has OTP secret set up or not). With our current user management, local changes are not desirable. It seems the group was chosen because pam_succeed_if.so can only check a few details at runtime, like UID & groups of the user.
- When logging in using SSH Keys, OTP could be skipped. This would encourage users to use SSH Keys…