DEV Community

Alexey Melezhik
Alexey Melezhik

Posted on

Hardening Rocky Linux with DTAP test protocol

DTAP protocol is a lightweight testing protocol allowing to validate Linux infrastructure at ease. Here is a code example of how one can check that their Rocky Linux VM is secure enough (more Linux distributions are easy to check the same way).

First of all check scenarios are just plain Bash

The second thing check commands are pretty much the same as if one run them manually using old school ps/grep/exit code approach.

That makes DTAP appealing to operation people and devops who are already familiar with Linux standard tool chain.

So here is an example:

#!/bin/bash

export DTAP_SESSION=$(date +%s)

sudo systemctl is-enabled firewalld 2>&1 | dtap --box - \
--check srv-enabled \
--desc "firewalld srv is enabled"

sudo systemctl is-active firewalld 2>&1 | dtap --box - \
--check srv-active \
--desc "firewalld srv is active"

sudo firewall-cmd --list-all | dtap \
--check firewall-default-deny \
--box - \
--desc "firewall default policy is deny"

sudo sshd -T | dtap \
--check sshd-secure \
--box - \
--desc "sshd is secure"

getenforce | dtap \
--check selinux-enabled \
--box - \
--desc "selinux enabled and enforced"

cat /etc/selinux/config  | dtap \
--check selinux-config-ok \
--box - \
--desc "selinux config correct"


rpm -q lynis  2>&1 | dtap \
--check package-install-ok \
--box - \
--params pm=rpm \
--desc "lynis package is installed"

(sudo lynis system audit 2>&1; echo $?) | dtap \
--check  exit-ok \
--box - \
--desc "sudo lynis system audit exits OK"

dtap --report

ex_code=$?

if [[ ex_code -eq 1 ]]; then
    echo
    dtap --report --details --failures
fi
Enter fullscreen mode Exit fullscreen mode

Following test scenario ensures that some things are set on VM:

  • sshd configuration is secure ( so far that means no root login is allowed and password less authentication in place, more checks will be added in the future )

  • firewall service runs and has default deny all policy

  • selinux is enabled

  • lynis audit is installed and successfully runs on the system with no error


In real life you can add mode checks, just check ready to use checks available from DTAP distribution.

More checks are easy to add (contribution guide coming soon), so PRs are welcome. 🤗


The DTAP is very lightweight and easy to install. It follows simple client/server architecture.

Both clients and server are just go binaries, you may build them your self and install on your server, follow installation guide.

In nutshell client would run on target VM, execute Bash commands and send output to server that executes check rules against the output and results are send back to a client machine. You are free to have one central check rules executor server and install it on the same machine where you run tests

Check rules are powered by modern and super powerfull Raku language, you need to install check rules engine (Sparrow6) on a server machine. For Alpine and Rocky Linux there are native packages in place:

Rocky Linux:

sudo dnf install 'dnf-command(copr)' -y -q
sudo dnf copr enable grayeul/TestProj -y
sudo yum install raku-sparrow6 -y -q
Enter fullscreen mode Exit fullscreen mode

Alpine:

sudo apk add raku-sparrow6
Enter fullscreen mode Exit fullscreen mode

In the end here is example report run for one my test machine, oops , it's not secure enough ))

$ bash examples/hardening.sh 
DTAP report
session: 1784290463
===
firewalld srv is enabled ...... OK
firewalld srv is active ...... OK
firewall default policy is deny ...... OK
sshd is secure ...... FAIL
selinux enabled and enforced ...... OK
selinux config correct ...... OK
lynis package is installed ...... FAIL
sudo lynis system audit exits OK ...... FAIL

DTAP report
session: 1784290463
===
sshd is secure ...... FAIL
[report]
12:14:25 :: [sparrowtask] - run sparrow task .
12:14:25 :: [sparrowtask] - run [.], thing: .
[task run: task.bash - .]
[task stdout]
12:14:25 :: port 22
12:14:25 :: addressfamily any
12:14:25 :: listenaddress [::]:22
12:14:25 :: listenaddress 0.0.0.0:22
12:14:25 :: usepam yes
12:14:25 :: logingracetime 120
12:14:25 :: x11displayoffset 10
12:14:25 :: x11maxdisplays 1000
12:14:25 :: maxauthtries 6
12:14:25 :: maxsessions 10
12:14:25 :: clientaliveinterval 0
12:14:25 :: clientalivecountmax 3
12:14:25 :: requiredrsasize 2048
12:14:25 :: streamlocalbindmask 0177
12:14:25 :: permitrootlogin yes
12:14:25 :: ignorerhosts yes
12:14:25 :: ignoreuserknownhosts no
12:14:25 :: hostbasedauthentication no
12:14:25 :: hostbasedusesnamefrompacketonly no
12:14:25 :: pubkeyauthentication yes
12:14:25 :: kerberosauthentication no
12:14:25 :: kerberosorlocalpasswd yes
12:14:25 :: kerberosticketcleanup yes
12:14:25 :: kerberosuniqueccache no
12:14:25 :: kerberosusekuserok yes
12:14:25 :: gssapienablek5users no
12:14:25 :: gssapiauthentication yes
12:14:25 :: gssapicleanupcredentials no
12:14:25 :: gssapikeyexchange no
12:14:25 :: gssapistrictacceptorcheck yes
12:14:25 :: gssapistorecredentialsonrekey no
12:14:25 :: gssapikexalgorithms gss-curve25519-sha256-,gss-nistp256-sha256-,gss-group14-sha256-,gss-group16-sha512-
12:14:25 :: passwordauthentication no
12:14:25 :: kbdinteractiveauthentication no
12:14:25 :: printmotd no
12:14:25 :: printlastlog yes
12:14:25 :: x11forwarding yes
12:14:25 :: x11uselocalhost yes
12:14:25 :: permittty yes
12:14:25 :: permituserrc yes
12:14:25 :: strictmodes yes
12:14:25 :: tcpkeepalive yes
12:14:25 :: permitemptypasswords no
12:14:25 :: compression yes
12:14:25 :: gatewayports no
12:14:25 :: usedns no
12:14:25 :: allowtcpforwarding yes
12:14:25 :: allowagentforwarding yes
12:14:25 :: disableforwarding no
12:14:25 :: allowstreamlocalforwarding yes
12:14:25 :: streamlocalbindunlink no
12:14:25 :: fingerprinthash SHA256
12:14:25 :: exposeauthinfo no
12:14:25 :: pidfile /var/run/sshd.pid
12:14:25 :: modulifile /etc/ssh/moduli
12:14:25 :: xauthlocation /usr/bin/xauth
12:14:25 :: ciphers aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes128-gcm@openssh.com,aes128-ctr
12:14:25 :: macs hmac-sha2-256-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha1,umac-128@openssh.com,hmac-sha2-512
12:14:25 :: banner none
12:14:25 :: forcecommand none
12:14:25 :: chrootdirectory none
12:14:25 :: trustedusercakeys none
12:14:25 :: revokedkeys none
12:14:25 :: securitykeyprovider internal
12:14:25 :: authorizedprincipalsfile none
12:14:25 :: versionaddendum none
12:14:25 :: authorizedkeyscommand none
12:14:25 :: authorizedkeyscommanduser none
12:14:25 :: authorizedprincipalscommand none
12:14:25 :: authorizedprincipalscommanduser none
12:14:25 :: hostkeyagent none
12:14:25 :: kexalgorithms curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512
12:14:25 :: casignaturealgorithms ecdsa-sha2-nistp256,sk-ecdsa-sha2-nistp256@openssh.com,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519,sk-ssh-ed25519@openssh.com,rsa-sha2-256,rsa-sha2-512
12:14:25 :: hostbasedacceptedalgorithms ssh-ed25519-cert-v01@openssh.com,ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,sk-ssh-ed25519@openssh.com,sk-ecdsa-sha2-nistp256@openssh.com,rsa-sha2-512,rsa-sha2-256,ssh-rsa
12:14:25 :: hostkeyalgorithms ecdsa-sha2-nistp256,ecdsa-sha2-nistp256-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521,ecdsa-sha2-nistp521-cert-v01@openssh.com,ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com
12:14:25 :: pubkeyacceptedalgorithms ecdsa-sha2-nistp256,ecdsa-sha2-nistp256-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521,ecdsa-sha2-nistp521-cert-v01@openssh.com,ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com
12:14:25 :: loglevel INFO
12:14:25 :: syslogfacility AUTHPRIV
12:14:25 :: authorizedkeysfile .ssh/authorized_keys
12:14:25 :: hostkey /etc/ssh/ssh_host_rsa_key
12:14:25 :: hostkey /etc/ssh/ssh_host_ecdsa_key
12:14:25 :: hostkey /etc/ssh/ssh_host_ed25519_key
12:14:25 :: authenticationmethods any
12:14:25 :: subsystem sftp /usr/libexec/openssh/sftp-server
12:14:25 :: maxstartups 10:30:100
12:14:25 :: persourcemaxstartups none
12:14:25 :: persourcenetblocksize 32:128
12:14:25 :: permittunnel no
12:14:25 :: ipqos af21 cs1
12:14:25 :: rekeylimit 0 0
12:14:25 :: permitopen any
12:14:25 :: permitlisten any
12:14:25 :: permituserenvironment no
12:14:25 :: pubkeyauthoptions none
[task check]
# root login should be not allowed
stdout match <permitrootlogin no> False
# password auth should be disabled
stdout match <passwordauthentication no> True
=================
TASK CHECK FAIL

lynis package is installed ...... FAIL
[report]
12:14:27 :: [sparrowtask] - run sparrow task .@pm=rpm
12:14:27 :: [sparrowtask] - run [.], thing: .@pm=rpm
[task run: task.bash - .]
[task stdout]
12:14:27 :: package lynis is not installed
[task check]
stdout match (w) <^^ \S+ $$> False
=================
TASK CHECK FAIL

sudo lynis system audit exits OK ...... FAIL
[report]
12:14:29 :: [sparrowtask] - run sparrow task .
12:14:29 :: [sparrowtask] - run [.], thing: .
[task run: task.bash - .]
[task stdout]
12:14:29 :: sudo: lynis: command not found
12:14:29 :: 1
[task check]
stdout match <:any:> True
<exit code found> True
# exit code: 1
<exit code == 0> False
=================
TASK CHECK FAIL
Enter fullscreen mode Exit fullscreen mode

If you like the tool please give it a start oh GH page or just start using it.

Thanks! 😊 🙏 😍

Top comments (0)