From 708efd90ca970ac446f4e8453d07e892b4cf033f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lesimple?= Date: Fri, 24 Mar 2023 08:51:40 +0000 Subject: [PATCH] chore: add RockyLinux 9 support --- .github/workflows/tests.yml | 4 +- README.md | 4 +- bin/admin/install | 1 + bin/admin/packages-check.sh | 19 ++-- doc/sphinx/installation/basic.rst | 4 +- docker/Dockerfile.rockylinux9 | 27 ++++++ etc/ssh/ssh_config.centos9 | 115 ++++++++++++++++++++++++ etc/ssh/sshd_config.centos9 | 142 ++++++++++++++++++++++++++++++ 8 files changed, 305 insertions(+), 11 deletions(-) create mode 100644 docker/Dockerfile.rockylinux9 create mode 100644 etc/ssh/ssh_config.centos9 create mode 100644 etc/ssh/sshd_config.centos9 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 15f0e98..c645838 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -20,7 +20,7 @@ jobs: name: Long strategy: matrix: - platform: [rockylinux8, debian11, 'opensuse15@opensuse/leap:15.4', ubuntu2204] + platform: [rockylinux9, debian11, 'opensuse15@opensuse/leap:15.4', ubuntu2204] 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, rockylinux8, debian9, debian10, debian11, debian12, 'opensuse15@opensuse/leap:15.4', ubuntu1604, ubuntu1804, ubuntu2004, ubuntu2204] + platform: [centos7, rockylinux8, rockylinux9, debian9, debian10, debian11, debian12, 'opensuse15@opensuse/leap:15.4', ubuntu1604, ubuntu1804, ubuntu2004, ubuntu2204] runs-on: ubuntu-latest if: contains(github.event.pull_request.labels.*.name, 'tests:full') steps: diff --git a/README.md b/README.md index cb3e65d..5aa01a1 100644 --- a/README.md +++ b/README.md @@ -72,9 +72,9 @@ 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 11 (Bullseye), Debian 10 (Buster), 9 (Stretch) +- Debian 11 (Bullseye), 10 (Buster), 9 (Stretch) - CentOS 7.x -- RockyLinux 8.x +- RockyLinux 8.x, 9.x - Ubuntu LTS 22.04, 20.04, 18.04, 16.04 - OpenSUSE Leap 15.4\* diff --git a/bin/admin/install b/bin/admin/install index efaf704..cc46e76 100755 --- a/bin/admin/install +++ b/bin/admin/install @@ -267,6 +267,7 @@ if [ "${opt[modify-ssh-config]}" = 1 ] || [ "${opt[modify-sshd-config]}" = 1 ] ; 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 + [ "$short_suffix_name" = "rocky9" ] && short_suffix_name=centos9 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 diff --git a/bin/admin/packages-check.sh b/bin/admin/packages-check.sh index 605b828..c0af883 100755 --- a/bin/admin/packages-check.sh +++ b/bin/admin/packages-check.sh @@ -56,15 +56,15 @@ if echo "$DISTRO_LIKE" | grep -q -w debian; then installed=$(dpkg -l | awk '/^ii/ {print $2}' | cut -d: -f1) install_cmd="apt-get install" elif echo "$DISTRO_LIKE" | grep -q -w rhel; then - wanted_list="perl-JSON perl-Net-Netmask perl-Net-IP \ - perl-Net-DNS perl-DBD-SQLite perl-TermReadKey \ + wanted_list="perl perl-JSON perl-Net-Netmask perl-Net-IP \ + perl-Net-DNS perl-DBD-SQLite perl-TermReadKey procps-ng \ sudo fping xz sqlite binutils acl gnupg2 rsync perl-DateTime \ perl-JSON-XS inotify-tools lsof curl perl-Term-ReadLine-Gnu \ perl-libwww-perl perl-Digest perl-Net-Server cryptsetup mosh \ expect openssh-server netcat bash perl-CGI perl-Test-Simple passwd \ cracklib-dicts perl-Time-Piece perl-Time-HiRes diffutils \ perl-Sys-Syslog pamtester google-authenticator qrencode-libs \ - perl-LWP-Protocol-https perl-Test-Deep findutils tar" + perl-LWP-Protocol-https perl-Test-Deep findutils tar iputils" if [ "$DISTRO_VERSION_MAJOR" = 7 ]; then wanted_list="$wanted_list fortune-mod coreutils util-linux" else @@ -74,7 +74,7 @@ elif echo "$DISTRO_LIKE" | grep -q -w rhel; then if [ "$opt_install" = 1 ]; then - if [ "$DISTRO_VERSION_MAJOR" = 8 ]; then + if [ "$DISTRO_VERSION_MAJOR" -ge 8 ]; then # in December 2020, they added "-Linux" to their repo name, so trying both combinations # also try with "Rocky-" for RockyLinux for repo in PowerTools Extras @@ -93,8 +93,17 @@ elif echo "$DISTRO_LIKE" | grep -q -w rhel; then fi $dnf_or_yum makecache $dnf_or_yum install -y epel-release + if [ -x /usr/bin/crb ]; then + action_detail "Enabling CRB..." + /usr/bin/crb enable + fi + if [ "$DISTRO_VERSION_MAJOR" -ge 9 ]; then + extraopts='--allowerasing' + else + extraopts='' + fi # shellcheck disable=SC2086 - $dnf_or_yum install -y $wanted_list + $dnf_or_yum install -y $extraopts $wanted_list exit 0 fi diff --git a/doc/sphinx/installation/basic.rst b/doc/sphinx/installation/basic.rst index 94a7fe2..7a13300 100644 --- a/doc/sphinx/installation/basic.rst +++ b/doc/sphinx/installation/basic.rst @@ -32,9 +32,9 @@ some of the below steps will be done by Puppet. Hence, you might want to only co 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 11 (Bullseye), Debian 10 (Buster), 9 (Stretch) +- Debian 11 (Bullseye), 10 (Buster), 9 (Stretch) - CentOS 7.x -- RockyLinux 8.x +- RockyLinux 8.x, 9.x - Ubuntu LTS 22.04, 20.04, 18.04, 16.04 - OpenSUSE Leap 15.4\* diff --git a/docker/Dockerfile.rockylinux9 b/docker/Dockerfile.rockylinux9 new file mode 100644 index 0000000..29685f8 --- /dev/null +++ b/docker/Dockerfile.rockylinux9 @@ -0,0 +1,27 @@ +FROM rockylinux:9 +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.centos9 b/etc/ssh/ssh_config.centos9 new file mode 100644 index 0000000..d8217f6 --- /dev/null +++ b/etc/ssh/ssh_config.centos9 @@ -0,0 +1,115 @@ +# Hardened SSH bastion config -- modify wisely! +# Based on https://wiki.mozilla.org/Security/Guidelines/OpenSSH +# With modifications where applicable/needed + +# hardened params follow. every non-needed feature is disabled by default, +# following the principle of least rights and least features (more enabled +# features mean a more important attack surface). + +# === FEATURES === + +# disable non-needed sshd features +Tunnel no +ForwardAgent no +ForwardX11 no +GatewayPorts no +ControlMaster no + +# === CRYPTOGRAPHY === + +# enforce the use of ssh version 2 protocol, version 1 is disabled. +# all sshd_config options regarding protocol 1 are therefore omitted. +Protocol 2 + +# list of allowed ciphers. +# chacha20-poly1305 is a modern cipher, considered very secure +# aes is still the standard, we prefer gcm cipher mode, but also +# allow ctr cipher mode for compatibility (ctr is considered secure) +# we deny arcfour(rc4), 3des, blowfish and cast +# for older remote servers (or esoteric hardware), we might need to add: aes256-cbc,aes192-cbc,aes128-cbc +# known gotchas: +# - BSD (https://lists.freebsd.org/pipermail/freebsd-bugs/2013-June/053005.html) needs aes256-gcm@openssh.com,aes128-gcm@openssh.com DISABLED +# - Old Cisco IOS (such as v12.2) only supports aes128-cbc,3des-cbc,aes192-cbc,aes256-cbc +# - Ancient Debians (Sarge) and RedHats (7) only support aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se,aes128-ctr,aes192-ctr,aes256-ctr +Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr + +# list of allowed message authentication code algorithms. +# etm (encrypt-then-mac) are considered the more secure, we +# prefer umac (has been proven secure) then sha2. +# for older remote servers, fallback to the non-etm version of +# the algorithms. we deny md5 entirely. +# for older remote servers (or esoteric hardware), we might need to add: hmac-sha1 +# Known gotchas: +# - Old Cisco IOS (such as v12.2) only supports hmac-sha1,hmac-sha1-96,hmac-md5,hmac-md5-96 +# - Ancient Debians (Sarge) and RedHats (7) only support hmac-md5,hmac-sha1,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96 +MACs umac-128-etm@openssh.com,umac-64-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128@openssh.com,umac-64@openssh.com,hmac-sha2-512,hmac-sha2-256 + +# List of allowed key exchange algorithms. +# we prefer curve25519-sha256 which is considered the most modern/secure, +# and still allow diffie hellman with group exchange using sha256 which is +# the most secure dh-based kex. +# we avoid algorithms based on the disputed NIST curves, and anything based +# on sha1. +# known gotchas: +# - Windows needs diffie-hellman-group14-sha1 and also needs to NOT have diffie-hellman-group-exchange-sha1 present in the list AT ALL +# - OmniOS 5.11 needs diffie-hellman-group1-sha1 +# - Old Cisco IOS (such as v12.2) only supports diffie-hellman-group1-sha1 +# - Ancient Debians (Sarge) and RedHats (7) only support diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1 +KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256 + +# === AUTHENTICATION === + +# we allow only public key authentication ... +PubkeyAuthentication yes +# ... not password nor keyboard-interactive +# ... (set to yes if sshpass is to be used) +PasswordAuthentication no +# ChallengeResponseAuthentication=yes forces KbdInteractiveAuthentication=yes in the openssh code! +ChallengeResponseAuthentication yes +KbdInteractiveAuthentication yes +# ... not host-based +HostbasedAuthentication no +# ... and not gssapi auth. +GSSAPIAuthentication no +GSSAPIKeyExchange no +GSSAPIDelegateCredentials no +# now we specify the auth methods order we want for manual ssh calls. +# NOTE1: as per the ssh source code, an auth method omitted hereafter +# will not be used, even if set to "yes" above. +# NOTE2: the bastion code (namely, ttyrec), will always set the proper +# value explicitly on command-line (pubkey OR sshpass), so the value +# 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,keyboard-interactive + +# === LOGIN ### + +# disable escape character use +EscapeChar none + +# detect if a hostkey changed due to DNS spoofing +CheckHostIP yes + +# ignore ssh-agent, only use specified keys (-i) +IdentitiesOnly yes +# disable auto-lookup of ~/.ssh/id_rsa ~/.ssh/id_ecdsa etc. +IdentityFile /dev/non/existent/file + +# carry those vars to the other side (includes LC_BASTION) +SendEnv LANG LC_* + +# allow usage of SSHFP DNS records +VerifyHostKeyDNS ask + +# yell if remote hostkey changed +StrictHostKeyChecking ask + +# === SYSTEM === + +# don't hash the users known_hosts files, in the context of a bastion, this adds no security +HashKnownHosts no + +# send an ssh ping each 57 seconds to the client and disconnect after 5 no-replies +ServerAliveInterval 57 +ServerAliveCountMax 5 diff --git a/etc/ssh/sshd_config.centos9 b/etc/ssh/sshd_config.centos9 new file mode 100644 index 0000000..a3e53f4 --- /dev/null +++ b/etc/ssh/sshd_config.centos9 @@ -0,0 +1,142 @@ +# Hardened SSHD bastion config -- modify wisely! +# Based on https://wiki.mozilla.org/Security/Guidelines/OpenSSH +# With additional restrictions where applicable + +# -lo and -rt users only have local console login +DenyUsers *-rt +DenyUsers *-lo + +# hardened params follow. every non-needed feature is disabled by default, +# following the principle of least rights and least features (more enabled +# features mean a more important attack surface). + +# === FEATURES === + +# disable non-needed sshd features +AllowAgentForwarding no +AllowTcpForwarding no +AllowStreamLocalForwarding no +X11Forwarding no +PermitTunnel no +PermitUserEnvironment no +PermitUserRC no +GatewayPorts no + +# === INFORMATION DISCLOSURE === + +# however, display a legal notice for each connection +Banner /etc/ssh/banner + +# don't print the bastion MOTD on connection +PrintMotd no + +# === CRYPTOGRAPHY === + +# enforce the use of ssh version 2 protocol, version 1 is disabled. +# all sshd_config options regarding protocol 1 are therefore omitted. +Protocol 2 + +# only use hostkeys with secure algorithms, and omit the ones using NIST curves +HostKey /etc/ssh/ssh_host_ed25519_key +HostKey /etc/ssh/ssh_host_rsa_key + +# list of allowed ciphers. +# chacha20-poly1305 is a modern cipher, considered very secure +# aes is still the standard, we prefer gcm cipher mode, but also +# allow ctr cipher mode for compatibility (ctr is still considered secure) +# we deny arcfour(rc4), 3des, blowfish and cast +Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr + +# list of allowed message authentication code algorithms. +# etm (encrypt-then-mac) are considered the more secure, we +# prefer umac (has been proven secure) then sha2. +# for older ssh client, fallback to the non-etm version of +# the algorithms. +# we deny md5 and sha1 +MACs umac-128-etm@openssh.com,umac-64-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128@openssh.com,umac-64@openssh.com,hmac-sha2-512,hmac-sha2-256 + +# List of allowed key exchange algorithms. +# we prefer curve25519-sha256 which is considered the most modern/secure, +# and still allow diffie hellman with group exchange using sha256 which is +# the most secure dh-based kex. +# we avoid algorithms based on the disputed NIST curves, and anything based +# on sha1. +KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256 + +# force rekey every 512M of data or 6 hours of connection, whichever comes first +RekeyLimit 512M 6h + +# === AUTHENTICATION === + +# we allow only public key authentication ... +PubkeyAuthentication yes +# ... not password +PasswordAuthentication no +# ... keyboard interactive (needed for MFA through PAM) +KbdInteractiveAuthentication yes +# ... not kerberos +KerberosAuthentication no +# ... challenge-response (needed for MFA through PAM) +ChallengeResponseAuthentication yes +# ... not host-based +HostbasedAuthentication no +# ... and not gssapi auth. +GSSAPIAuthentication no +GSSAPIKeyExchange no + +# just in case, we also explicitly deny empty passwords +PermitEmptyPasswords no + +# 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 === + +# disconnect after 30 seconds if user didn't log in successfully +LoginGraceTime 30 + +# not more than 1 session per network connection (connection sharing with ssh client's master/shared mode) +MaxSessions 1 + +# maximum concurrent unauth connections to the sshd daemon +MaxStartups 50:30:500 + +# accept LANG and LC_* vars (also includes LC_BASTION) +AcceptEnv LANG LC_* + +# === SYSTEM === + +# sshd log level at verbose in auth facility for auditing purposes +LogLevel VERBOSE +SyslogFacility AUTH + +# check sanity of user HOME dir before allowing user to login +StrictModes yes + +# never use dns (slows down connections) +UseDNS no + +# use PAM facility +UsePAM yes + +# === AuthenticationMethods vs potential root OTP vs potential user MFA === +# If 2FA has been configured for root, we force pubkey+PAM for it. If this is the case +# on your system, uncomment the next two lines (see +# https://ovh.github.io/the-bastion/installation/advanced.html#fa-root-authentication) +#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