Jakoś na początku roku 2020 na Wydziale Biologii i Biotechnologii, decyzją Pani Dziekan powstało Wydziałowe Centrum Bioinformatyczne. W skład tego zespołu oprócz mnie weszło jeszcze dwie osoby, które stricte zajmują bioinformatyką. Ja w zespole odpowiadam za administrację kilkoma maszynami, na których po najmniejszej linii oporu zainstalowany jest linuks, dokładniej to jedna z dystybucji, Ubuntu.

Ostatnio zadaniem, było zainstalowanie na jednej z maszyn Rstudio Server. Z racji oszczędności wybór padł na wersję Open Source. Zainstalowanie i uruchomienie Rstudio nie jest jakimś szczególnym wyzwaniem, tym bardziej, że dostępny jest oficjalny przepis 😉. Po zainstalowaniu, prośba do administratora sieci uczelnianej o “wystawienie” aplikacji na “świat”. I tu pojawia się problem. Wersja otwartoźródłowa Rstudio umożliwia tylko jeden sposób logowania się do aplikacji, za pomocą linuksowego PAM. Żeby ten sposób był w miarę bezpieczny można było zrobić dwie rzeczy:

  • użyć skomplikowanego hasła użytkownika, które jednocześnie jest hasłem użytkownika w systemie na VPS (dziękuję bardzo, za używanie takiego rozwiązania na codzień)

  • “doposażyć” PAM w dodatkowy moduł, Google Authenticator PAM module.

Wybór padł na to drugie rozwiązanie. Instalacja bajka, bo okazuje się że sama paczka, w przypadku Ubuntu nazywa się libpam-google-authenticator, jest dostępna w wielu dystrybucjach linuks.

Instalacja to jedno, konfiguracja to drugie. Z pomocą pierwotnie przyszło mi słynne Arch Linux Wiki. Jednak opisany jest tam sposób konfiguracji daemona ssh (sshd). Nie wiedziałem jak zabrać się za autentykację Rstudio. Zacząłem przeglądać oficjalną dokumentację Rstudio i natknąłem się na rozdział 3 Authenticating Users. Długo mi zajęło, żeby ustawić poprawnie sposób logowania z wykorzystaniem google auth module do PAM. Finalnie należy zrobić dokładnie to co jest opisane w dokumentacji, ale dla RedHat / CentOS / SUSE.

sudo cp /etc/pam.d/login /etc/pam.d/rstudio

Następnie do pliku należy dodać linię, ja dodałem na samym początku pliku rstudio

auth            required        pam_google_authenticator.so

Z tego co jest napisane na archowym Wiki, po to aby używać obu metod autentykacji jednocześnie, co potem zostało wyłączone, z uwagi na to że strona logowania Rstudio nie wspiera dwustopniowego logowania. Należy wyedytować plik i zahashować linię u mnie 57 dotyczącą Standard Un*x authentication #@include common-auth. Plik w całości wygląda tak.

cat /etc/pam.d/rstudio

#
# The PAM configuration file for the Shadow `login' service
#
auth            required      pam_google_authenticator.so
# Enforce a minimal delay in case of failure (in microseconds).
# (Replaces the `FAIL_DELAY' setting from login.defs)
# Note that other modules may require another minimal delay. (for example,
# to disable any delay, you should add the nodelay option to pam_unix)
auth       optional   pam_faildelay.so  delay=3000000

# Outputs an issue file prior to each login prompt (Replaces the
# ISSUE_FILE option from login.defs). Uncomment for use
# auth       required   pam_issue.so issue=/etc/issue

# Disallows other than root logins when /etc/nologin exists
# (Replaces the `NOLOGINS_FILE' option from login.defs)
auth       requisite  pam_nologin.so

# SELinux needs to be the first session rule. This ensures that any
# lingering context has been cleared. Without this it is possible
# that a module could execute code in the wrong domain.
# When the module is present, "required" would be sufficient (When SELinux
# is disabled, this returns success.)
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close

# Sets the loginuid process attribute
session    required     pam_loginuid.so

# Prints the message of the day upon successful login.
# (Replaces the `MOTD_FILE' option in login.defs)
# This includes a dynamically generated part from /run/motd.dynamic
# and a static (admin-editable) part from /etc/motd.
session    optional   pam_motd.so motd=/run/motd.dynamic
session    optional   pam_motd.so noupdate

# SELinux needs to intervene at login time to ensure that the process
# starts in the proper default security context. Only sessions which are
# intended to run in the user's context should be run after this.
# pam_selinux.so changes the SELinux context of the used TTY and configures
# SELinux in order to transition to the user context with the next execve()
# call.
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open
# When the module is present, "required" would be sufficient (When SELinux
# is disabled, this returns success.)

# This module parses environment configuration file(s)
# and also allows you to use an extended config
# file /etc/security/pam_env.conf.
# 
# parsing /etc/environment needs "readenv=1"
session       required   pam_env.so readenv=1
# locale variables are also kept into /etc/default/locale in etch
# reading this file *in addition to /etc/environment* does not hurt
session       required   pam_env.so readenv=1 envfile=/etc/default/locale

# Standard Un*x authentication.
#@include common-auth

# This allows certain extra groups to be granted to a user
# based on things like time of day, tty, service, and user.
# Please edit /etc/security/group.conf to fit your needs
# (Replaces the `CONSOLE_GROUPS' option in login.defs)
auth       optional   pam_group.so

# Uncomment and edit /etc/security/time.conf if you need to set
# time restraint on logins.
# (Replaces the `PORTTIME_CHECKS_ENAB' option from login.defs
# as well as /etc/porttime)
# account    requisite  pam_time.so

# Uncomment and edit /etc/security/access.conf if you need to
# set access limits.
# (Replaces /etc/login.access file)
# account  required       pam_access.so

# Sets up user limits according to /etc/security/limits.conf
# (Replaces the use of /etc/limits in old login)
session    required   pam_limits.so

# Prints the last login info upon successful login
# (Replaces the `LASTLOG_ENAB' option from login.defs)
session    optional   pam_lastlog.so

# Prints the status of the user's mailbox upon successful login
# (Replaces the `MAIL_CHECK_ENAB' option from login.defs). 
#
# This also defines the MAIL environment variable
# However, userdel also needs MAIL_DIR and MAIL_FILE variables
# in /etc/login.defs to make sure that removing a user 
# also removes the user's mail spool file.
# See comments in /etc/login.defs
session    optional   pam_mail.so standard

# Create a new session keyring.
session    optional   pam_keyinit.so force revoke

# Standard Un*x account and session
@include common-account
@include common-session
@include common-password

Teraz w zależności od używanego sprzętu, ja akurat mam telefon z androidem, zainstalować soft który będzie nam obsługiwał OTP.

Jeszcze dodanie użytkowników oraz wygenerowanie dla każdego z nich QR-kodów do google auth. Przykład z WIKI Archa.

$ google-authenticator
   Do you want authentication tokens to be time-based (y/n) y
   <Here you will see generated QR code>
   Your new secret key is: ZVZG5UZU4D7MY4DH
   Your verification code is 269371
   Your emergency scratch codes are:
     70058954
     97277505
     99684896
     56514332
     82717798

   Do you want me to update your "/home/username/.google_authenticator" file (y/n) y

   Do you want to disallow multiple uses of the same authentication
   token? This restricts you to one login about every 30s, but it increases
   your chances to notice or even prevent man-in-the-middle attacks (y/n) y

   By default, tokens are good for 30 seconds and in order to compensate for
   possible time-skew between the client and the server, we allow an extra
   token before and after the current time. If you experience problems with poor
   time synchronization, you can increase the window from its default
   size of 1:30min to about 4min. Do you want to do so (y/n) n

   If the computer that you are logging into is not hardened against brute-force
   login attempts, you can enable rate-limiting for the authentication module.
   By default, this limits attackers to no more than 3 login attempts every 30s.
   Do you want to enable rate-limiting (y/n) y

W momencie gdy mamy zainstalowany pakiet qrencode (akurat w Ubuntu instaluje się jako zależność do pakietu libpam-google-authenticator), pojawi się kod QR, za pomocą którego można w aplikacji na telefon dodać nasz serwer Rstudio.

Od teraz do zalogowania używamy tylko nazwy użytkownika z VPS oraz jednorazowego hasła, generowanego przez aplikację, które zmienia się co 30 sekund.

Ciekawe na ile to rozwiązanie okaże się bezpieczniejsze niż standardowe logowanie się hasłem użytkownika.