diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index d9464f4..be3b095 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -20,7 +20,7 @@ jobs:
name: Long
strategy:
matrix:
- platform: ['centos7@centos:7.9.2009', 'centos8@centos:8.3.2011', debian9, debian10, debian11, 'opensuse15@opensuse/leap:15.3', ubuntu1604, ubuntu1804, ubuntu2004]
+ platform: [rockylinux8, debian10, 'opensuse15@opensuse/leap:15.3', ubuntu2004]
runs-on: ubuntu-latest
if: contains(github.event.pull_request.labels.*.name, 'tests:long')
steps:
@@ -34,7 +34,7 @@ jobs:
name: Full
strategy:
matrix:
- platform: ['centos7@centos:7.7.1908', 'centos7@centos:7.8.2003', 'centos7@centos:7.9.2009', 'centos8@centos:8.1.1911', 'centos8@centos:8.2.2004', 'centos8@centos:8.3.2011', debian9, debian10, debian11, 'opensuse15@opensuse/leap:15.2', 'opensuse15@opensuse/leap:15.3', ubuntu1604, ubuntu1804, ubuntu2004]
+ platform: [centos7, centos8, rockylinux8, debian9, debian10, debian11, 'opensuse15@opensuse/leap:15.3', ubuntu1604, ubuntu1804, ubuntu2004]
runs-on: ubuntu-latest
if: contains(github.event.pull_request.labels.*.name, 'tests:full')
steps:
diff --git a/README.md b/README.md
index 2fbcf33..5fda360 100644
--- a/README.md
+++ b/README.md
@@ -72,10 +72,11 @@ Also don't forget to customize your `bastion.conf` file, which can be found in `
Linux distros below are tested with each release, but as this is a security product, you are **warmly** advised to run it on the latest up-to-date stable version of your favorite OS:
-- Debian 10 (Buster), 9 (Stretch)
-- RHEL/CentOS 8.x (8.3.2011, 8.2.2004, 8.1.1911), 7.x (7.9.2009, 7.8.2003, 7.7.1908)
+- Debian 11 (Bullseye), Debian 10 (Buster), 9 (Stretch)
+- RHEL/CentOS 8.x, 7.x
+- RockyLinux 8.x
- Ubuntu LTS 20.04, 18.04, 16.04
-- OpenSUSE Leap 15.3\*, 15.2\*
+- OpenSUSE Leap 15.3\*
\*: Note that these versions have no out-of-the-box MFA support, as they lack packaged versions of `pamtester`, `pam-google-authenticator`, or both. Of course, you may compile those yourself.
Any other so-called "modern" Linux version are not tested with each release, but should work with no or minor adjustments.
@@ -86,7 +87,7 @@ The following OS are also tested with each release:
\*\*: Note that these have partial MFA support, due to their reduced set of available `pam` plugins. Support for either an additional password or TOTP factor can be configured, but not both at the same time. The code is actually known to work on FreeBSD/HardenedBSD 10+, but it's only regularly tested under 13.0.
-Other BSD variants, namely OpenBSD 5.4+ and NetBSD 7+ partially work but are unsupported and discouraged as they have a severe limitation over the maximum number of supplementary groups, causing problems for group membership and restricted commands checks, as well as no filesystem-level ACL support and missing PAM support (hence no MFA).
+Other BSD variants, such as OpenBSD and NetBSD, are unsupported as they have a severe limitation over the maximum number of supplementary groups, causing problems for group membership and restricted commands checks, as well as no filesystem-level ACL support and missing PAM support (hence no MFA).
### Zero assumption on your environment
diff --git a/bin/admin/check-ssh-hardening.pl b/bin/admin/check-ssh-hardening.pl
index 65dd580..959717e 100755
--- a/bin/admin/check-ssh-hardening.pl
+++ b/bin/admin/check-ssh-hardening.pl
@@ -394,8 +394,7 @@ check_config_value 'IgnoreRHosts', 'no', 'yes';
check_config_value 'StrictModes', 'yes', 'yes';
check_config_value 'PermitRootLogin', 'yes', [qw{ no without-password forbid-password }];
check_config_value 'PermitEmptyPasswords', 'no', 'no';
-check_config_value 'UsePrivilegeSeparation', 'yes', [qw{ yes sandbox }];
-check_config_value 'PermitTunnel', 'yes', [qw{ 0 no }];
+check_config_value 'PermitTunnel', 'yes', [qw{ 0 no }];
check_config_value 'AllowAgentForwarding', 'yes', 'no';
check_config_value 'AllowTcpForwarding', 'yes', 'no';
diff --git a/bin/admin/install b/bin/admin/install
index b4f9232..8ab0e76 100755
--- a/bin/admin/install
+++ b/bin/admin/install
@@ -244,6 +244,7 @@ fi
if [ "${opt[modify-ssh-config]}" = 1 ] || [ "${opt[modify-sshd-config]}" = 1 ] ; then
action_doing "Find which ssh/sshd config templates to install on $OS_FAMILY $LINUX_DISTRO $DISTRO_VERSION"
short_suffix_name=$(echo "$LINUX_DISTRO$DISTRO_VERSION_MAJOR" | sed -re "s/[^a-z0-9]//")
+ [ "$short_suffix_name" = "rocky8" ] && short_suffix_name=centos8
filesuffix=default
if [ -e "$basedir/etc/ssh/sshd_config.$short_suffix_name" ] && [ -e "$basedir/etc/ssh/ssh_config.$short_suffix_name" ]; then
filesuffix=$short_suffix_name
@@ -253,8 +254,10 @@ if [ "${opt[modify-ssh-config]}" = 1 ] || [ "${opt[modify-sshd-config]}" = 1 ] ;
filesuffix=debian7
elif [ "$DISTRO_VERSION_MAJOR" -le 16 ]; then
filesuffix=debian8
- else
+ elif [ "$DISTRO_VERSION_MAJOR" -le 18 ]; then
filesuffix=debian10
+ else
+ filesuffix=debian11
fi
elif echo "$DISTRO_LIKE" | grep -q -w suse; then
filesuffix=opensuse15
diff --git a/bin/admin/packages-check.sh b/bin/admin/packages-check.sh
index 4619b58..20ecdc7 100755
--- a/bin/admin/packages-check.sh
+++ b/bin/admin/packages-check.sh
@@ -76,7 +76,7 @@ elif echo "$DISTRO_LIKE" | grep -q -w rhel; then
expect openssh-server nc bash perl-CGI perl(Test::More) passwd \
cracklib-dicts perl-Time-Piece perl-Time-HiRes diffutils \
perl-Sys-Syslog pamtester google-authenticator qrencode-libs \
- util-linux-user perl-LWP-Protocol-https"
+ util-linux-user perl-LWP-Protocol-https findutils"
if [ "$DISTRO_VERSION_MAJOR" = 7 ]; then
wanted_list="$wanted_list fortune-mod coreutils"
fi
@@ -87,10 +87,14 @@ elif echo "$DISTRO_LIKE" | grep -q -w rhel; then
if [ "$opt_install" = 1 ]; then
if [ "$DISTRO_VERSION_MAJOR" = 8 ]; then
# in December 2020, they added "-Linux" to their repo name, so trying both combinations
- for repo in CentOS-PowerTools CentOS-Extras CentOS-Linux-PowerTools CentOS-Linux-Extras
+ # also try with "Rocky-" for RockyLinux
+ for repo in PowerTools Extras
do
- test -f /etc/yum.repos.d/$repo.repo || continue
- sed -i -e 's/enabled=.*/enabled=1/g' /etc/yum.repos.d/$repo.repo
+ for prefix in CentOS CentOS-Linux Rocky
+ do
+ test -f /etc/yum.repos.d/$prefix-$repo.repo || continue
+ sed -i -e 's/enabled=.*/enabled=1/g' /etc/yum.repos.d/$prefix-$repo.repo
+ done
done
fi
if command -v dnf >/dev/null; then
diff --git a/doc/sphinx/installation/basic.rst b/doc/sphinx/installation/basic.rst
index c792d60..c9f6a94 100644
--- a/doc/sphinx/installation/basic.rst
+++ b/doc/sphinx/installation/basic.rst
@@ -26,24 +26,22 @@ We published a Puppet module to handle The Bastion configuration and prerequisit
The following Linux distros are tested with each release, but as this is a security product, you are *warmly* advised to run it on the latest up-to-date stable version of your favorite OS:
-- Debian 10 (Buster), 9 (Stretch)
-- RHEL/CentOS 8.x (8.3.2011, 8.2.2004, 8.1.1911), 7.x (7.9.2009, 7.8.2003, 7.7.1908)
+- Debian 11 (Bullseye), Debian 10 (Buster), 9 (Stretch)
+- RHEL/CentOS 8.x, 7.x
+- RockyLinux 8.x
- Ubuntu LTS 20.04, 18.04, 16.04
-- OpenSUSE Leap 15.3\*, 15.2\*
+- OpenSUSE Leap 15.3\*
\*: Note that these versions have no out-of-the-box MFA support, as they lack packaged versions of ``pamtester``, ``pam-google-authenticator``, or both. Of course, you may compile those yourself.
Any other so-called `modern` Linux version are not tested with each release, but should work with no or minor adjustments.
The following OS are also tested with each release:
-- FreeBSD/HardenedBSD 12.1\*\*
+- FreeBSD/HardenedBSD 13.0\*\*
-\*\*: Note that these have partial MFA support, due to their reduced set of available ``pam`` plugins. Support for either an additional password or TOTP factor can be configured, but not both at the same time. The code is actually known to work on FreeBSD/HardenedBSD 10+, but it's only regularly tested under 12.1.
+\*\*: Note that these have partial MFA support, due to their reduced set of available ``pam`` plugins. Support for either an additional password or TOTP factor can be configured, but not both at the same time. The code is actually known to work on FreeBSD/HardenedBSD 10+, but it's only regularly tested under 13.0.
-Other BSD variants partially work but are unsupported and discouraged as they have a severe limitation over the maximum number of supplementary groups (causing problems for group membership and restricted commands checks), no filesystem-level ACL support and missing MFA:
-
-- OpenBSD 5.4+
-- NetBSD 7+
+Other BSD variants, such as OpenBSD and NetBSD, are unsupported as they have a severe limitation over the maximum number of supplementary groups, causing problems for group membership and restricted commands checks, as well as no filesystem-level ACL support and missing PAM support (hence no MFA).
In any case, you are expected to install this on a properly secured machine (including, but not limited to: ``iptables``/``pf``, reduced-set of installed software and daemons, general system hardening, etc.). If you use Debian, following the `CIS Hardening guidelines `_ is a good start. We have `a tool `_ to check for compliance against these guidelines. If you use Debian and don't yet have your own hardened template, this script should help you getting up to speed, and ensuring your hardened host stays hardened over time, through a daily audit you might want to setup through cron.
diff --git a/docker/Dockerfile.centos7 b/docker/Dockerfile.centos7
index c2e16c3..b7ddb7f 100644
--- a/docker/Dockerfile.centos7
+++ b/docker/Dockerfile.centos7
@@ -25,4 +25,3 @@ RUN ["/opt/bastion/bin/admin/install","--new-install"]
ENTRYPOINT /opt/bastion/docker/entrypoint.sh
# TESTOPT --has-mfa=1 --has-pamtester=1 --has-piv=1
-# TESTFROM centos:7.9.2009 centos:7.8.2003 centos:7.7.1908
diff --git a/docker/Dockerfile.centos8 b/docker/Dockerfile.centos8
index 1a904b6..f2a609e 100644
--- a/docker/Dockerfile.centos8
+++ b/docker/Dockerfile.centos8
@@ -25,4 +25,3 @@ RUN ["/opt/bastion/bin/admin/install","--new-install"]
ENTRYPOINT /opt/bastion/docker/entrypoint.sh
# TESTOPT --has-mfa=1 --has-pamtester=1 --has-piv=1
-# TESTFROM centos:8.3.2011 centos:8.2.2004 centos:8.1.1911
diff --git a/docker/Dockerfile.rockylinux8 b/docker/Dockerfile.rockylinux8
new file mode 100644
index 0000000..af2cd90
--- /dev/null
+++ b/docker/Dockerfile.rockylinux8
@@ -0,0 +1,27 @@
+FROM rockylinux:8
+LABEL maintainer="stephane.lesimple+bastion@ovhcloud.com"
+
+# cache builds efficiently: just copy the scripts to install packages first
+COPY bin/admin/install-ttyrec.sh bin/admin/install-yubico-piv-checker.sh bin/admin/packages-check.sh /opt/bastion/bin/admin/
+COPY lib/shell /opt/bastion/lib/shell/
+RUN ["/opt/bastion/bin/admin/packages-check.sh","-i","-d","-s"]
+RUN ["/opt/bastion/bin/admin/install-ttyrec.sh","-r"]
+RUN ["/opt/bastion/bin/admin/install-yubico-piv-checker.sh","-r"]
+
+# disable /dev/kmsg handling by syslog-ng and explicitly enable /dev/log
+RUN test -e /etc/syslog-ng/syslog-ng.conf && \
+ sed -i -re 's=system\(\);=unix-stream("/dev/log");=' /etc/syslog-ng/syslog-ng.conf
+
+# at each modification of our code, we'll start from here thanks to build cache
+COPY . /opt/bastion
+
+# tests that the environment works
+RUN ["/opt/bastion/bin/dev/perl-check.sh"]
+
+# setup ssh/sshd config and setup bastion install
+RUN ["/opt/bastion/bin/admin/install","--new-install"]
+
+# start at entrypoint
+ENTRYPOINT /opt/bastion/docker/entrypoint.sh
+
+# TESTOPT --has-mfa=1 --has-pamtester=1 --has-piv=1
diff --git a/etc/ssh/ssh_config.default b/etc/ssh/ssh_config.default
index accf3b7..c74f7eb 100644
--- a/etc/ssh/ssh_config.default
+++ b/etc/ssh/ssh_config.default
@@ -68,8 +68,8 @@ PubkeyAuthentication yes
# ... (set to yes if sshpass is to be used)
PasswordAuthentication no
# ChallengeResponseAuthentication=yes forces KbdInteractiveAuthentication=yes in the openssh code!
-ChallengeResponseAuthentication no
-KbdInteractiveAuthentication no
+ChallengeResponseAuthentication yes
+KbdInteractiveAuthentication yes
# ... not host-based
HostbasedAuthentication no
# now we specify the auth methods order we want for manual ssh calls.
@@ -80,7 +80,7 @@ HostbasedAuthentication no
# specified hereafter will be ignored. if you want to force-disable
# a method, set it to "no" in the list above, as those will never be
# overridden by the code.
-PreferredAuthentications publickey
+PreferredAuthentications publickey,keyboard-interactive
# === LOGIN ###
diff --git a/etc/ssh/sshd_config.debian7 b/etc/ssh/sshd_config.debian7
index 929ee9f..0fb35f6 100644
--- a/etc/ssh/sshd_config.debian7
+++ b/etc/ssh/sshd_config.debian7
@@ -101,9 +101,6 @@ AcceptEnv LANG LC_*
# === SYSTEM ===
-# Use kernel sandbox mechanisms where possible in unprivilegied processes (seccomp)
-UsePrivilegeSeparation sandbox
-
# sshd log level at verbose in auth facility for auditing purposes
LogLevel VERBOSE
SyslogFacility AUTH
diff --git a/etc/ssh/sshd_config.debian8 b/etc/ssh/sshd_config.debian8
index 1733c31..421d17e 100644
--- a/etc/ssh/sshd_config.debian8
+++ b/etc/ssh/sshd_config.debian8
@@ -113,9 +113,6 @@ AcceptEnv LANG LC_*
# === SYSTEM ===
-# Use kernel sandbox mechanisms where possible in unprivilegied processes (seccomp)
-UsePrivilegeSeparation sandbox
-
# sshd log level at verbose in auth facility for auditing purposes
LogLevel VERBOSE
SyslogFacility AUTH
diff --git a/etc/ssh/sshd_config.debian9 b/etc/ssh/sshd_config.debian9
index 1733c31..421d17e 100644
--- a/etc/ssh/sshd_config.debian9
+++ b/etc/ssh/sshd_config.debian9
@@ -113,9 +113,6 @@ AcceptEnv LANG LC_*
# === SYSTEM ===
-# Use kernel sandbox mechanisms where possible in unprivilegied processes (seccomp)
-UsePrivilegeSeparation sandbox
-
# sshd log level at verbose in auth facility for auditing purposes
LogLevel VERBOSE
SyslogFacility AUTH
diff --git a/etc/ssh/sshd_config.default b/etc/ssh/sshd_config.default
index 5771263..f87d730 100644
--- a/etc/ssh/sshd_config.default
+++ b/etc/ssh/sshd_config.default
@@ -72,19 +72,21 @@ RekeyLimit 512M 6h
PubkeyAuthentication yes
# ... not password
PasswordAuthentication no
-# ... not keyboard interactive
-KbdInteractiveAuthentication no
-# ... not challenge-response
-ChallengeResponseAuthentication no
+# ... keyboard interactive (needed for MFA through PAM)
+KbdInteractiveAuthentication yes
+# ... challenge-response (needed for MFA through PAM)
+ChallengeResponseAuthentication yes
# ... not host-based
HostbasedAuthentication no
# just in case, we also explicitly deny empty passwords
PermitEmptyPasswords no
-# root login is allowed only with public keys, not passwords
-# this can be disabled entirely for auditing reasons (forcing admins to use sudo)
-PermitRootLogin without-password
+# this needs to be set at "yes" to allow PAM keyboard-interactive authentication,
+# which is not a security issue because the AuthenticationMethods below force the use of
+# either publickey or publickey+keyboard-interactive, hence password-only login is never
+# possible, for root or any other account for that matter
+PermitRootLogin yes
# === LOGIN ===
@@ -102,9 +104,6 @@ AcceptEnv LANG LC_*
# === SYSTEM ===
-# Use kernel sandbox mechanisms where possible in unprivilegied processes (seccomp)
-UsePrivilegeSeparation sandbox
-
# sshd log level at verbose in auth facility for auditing purposes
LogLevel VERBOSE
SyslogFacility AUTH
@@ -114,3 +113,20 @@ StrictModes yes
# never use dns (slows down connections)
UseDNS no
+
+# === AuthenticationMethods vs potential root OTP vs potential user MFA ===
+# 2FA has been configured for root, so we force pubkey+PAM for it
+#Match User root
+# AuthenticationMethods publickey,keyboard-interactive:pam
+# Unconditionally skip PAM auth for members of the bastion-nopam group
+Match Group bastion-nopam
+ AuthenticationMethods publickey
+# if in one of the mfa groups AND the osh-pubkey-auth-optional group, use publickey+pam OR pam
+Match Group mfa-totp-configd,mfa-password-configd Group osh-pubkey-auth-optional
+ AuthenticationMethods publickey,keyboard-interactive:pam keyboard-interactive:pam
+# if in one of the mfa groups, use publickey AND pam
+Match Group mfa-totp-configd,mfa-password-configd
+ AuthenticationMethods publickey,keyboard-interactive:pam
+# by default, always ask the publickey (no PAM)
+Match All
+ AuthenticationMethods publickey
diff --git a/tests/functional/tests.d/325-accountinfo.sh b/tests/functional/tests.d/325-accountinfo.sh
index 7fc981b..448c80b 100644
--- a/tests/functional/tests.d/325-accountinfo.sh
+++ b/tests/functional/tests.d/325-accountinfo.sh
@@ -43,7 +43,7 @@ testsuite_accountinfo()
json .value.already_seen_before 0 .value.last_activity null
json .value.max_inactive_days null
if [ "$OS_FAMILY" = Linux ]; then
- .value.password.date_changed $(date +%Y-%m-%d)
+ json .value.password.date_changed $(date +%Y-%m-%d)
fi
# a2 connects, which will update already_seen_before