the-bastion/doc/sphinx/installation/advanced.rst
2020-10-22 08:12:49 +00:00

316 lines
15 KiB
ReStructuredText

=====================
Advanced Installation
=====================
This section goes further in explaining how to setup your bastion. You should have completed the :doc:`basic installation<basic>` first.
Encryption & signature GPG keys
===============================
There are 2 pairs of GPG keys being used by the bastion:
- The *bastion GPG key*
* The **private** key is used by the **bastion** to **sign** the ttyrec files
* The **public** key is used by the **admins** to **verify** the signature and prove non-repudiation and non-tampering of the ttyrec files
- The *admins GPG key*
* The **public** key is used by the **bastion** to **encrypt** the backups and the ttyrec files
* The **private** key is used by the **admins** to **decrypt** the backups when a restore operation is needed, and the ttyrec files
Generating the bastion GPG key
******************************
Generate a GPG key that will be used by the bastion to sign files, this might take a while especially if the server is idle:
.. code-block:: shell
:emphasize-lines: 1
/opt/bastion/bin/admin/setup-gpg.sh --generate
gpg: directory `/root/.gnupg' created
gpg: Generating GPG key, it'll take some time.
Not enough random bytes available. Please do some other work to give
the OS a chance to collect more entropy! (Need 39 more bytes)
..........+++++
gpg: /root/.gnupg/trustdb.gpg: trustdb created
gpg: key A4480F26 marked as ultimately trusted
gpg: done
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
Configuration file /etc/bastion/osh-encrypt-rsync.conf.d/50-gpg-bastion-key.conf updated:
8<---8<---8<---8<---8<---8<--
# autogenerated with /opt/bastion/bin/admin/setup-gpg.sh at Wed Mar 21 10:03:08 CET 2018
{
"signing_key_passphrase": "************",
"signing_key": "5D3CFDFFA4480F26"
}
--->8--->8--->8--->8--->8--->8
Done.
While it's working, you can proceed to the section below.
Generating and importing the admins GPG key
*******************************************
You should import on the bastion one or more **public** GPG keys that'll be used for encryption. If you don't already have a GPG key for this, you can generate one. As this is the admin GPG key, don't generate it on the bastion itself. On the desk of the administrator (you?), you can run for example:
.. code-block:: shell
:emphasize-lines: 1-9
myname='John Doe'
email='jd@example.org'
bastion='mybastion4.example.org'
pass=`pwgen -sy 12 1`
echo "The passphrase for the key will be: $pass"
printf "Key-Type: RSA\nKey-Length: 4096\nSubkey-Type: RSA\nSubkey-Length: 4096\n" \
"Name-Real: %s\nName-Comment: %s\nName-Email: %s\nExpire-Date: 0\n" \
"Passphrase: %s\n%%echo Generating GPG key\n%%commit\n%%echo done\n" \
"$myname ($bastion)" $(date +%Y) "$email" "$pass" | gpg --gen-key --batch
The passphrase for the key will be: ************
gpg: Generating GPG key
Not enough random bytes available. Please do some other work to give
the OS a chance to collect more entropy! (Need 119 more bytes)
.....+++++
gpg: key D2BDF9B5 marked as ultimately trusted
gpg: done
Of course, adjust the ``myname``, ``email`` and ``bastion`` variables accordingly. Write down the passphrase in a secure vault. All bastions admins will need it if they are to decrypt ttyrec files later for inspection, and also decrypt the backup should a restore be needed. When the key is done being generated, get the public key with ``gpg -a --export D2BDF9B5``, using the proper key ID that you just generated. Copy it to your clipboard, then back to the bastion, paste it at the following prompt:
.. code-block:: shell
/opt/bastion/bin/admin/setup-gpg.sh --import
Also export the private admins GPG key to a secure vault (if you want the same key to be shared by the admins):
.. code-block:: shell
gpg --export-secret-keys --armor D2BDF9B5
Rotation, encryption & backup of ttyrec files
=============================================
You should already have all the needed GPG keys at the proper places, by following "Setup the encryption & signature GPG keys" section above.
The configuration file is located in ``/etc/bastion/osh-encrypt-rsync.conf``.
You can ignore the ``signing_key``, ``signing_key_passphrase`` and ``recipients`` options, as these have been auto-filled when you generated the GPG keys, by dropping configuration files in the ``/etc/bastion/osh-encrypt-rsync.conf.d`` directory. Any file there takes precedence over the global configuration file.
Once you are done with you configuration, you might want to test it by running:
.. code-block:: shell
/opt/bastion/bin/admin/osh-encrypt-rsync.pl --config-test
Or even go further by starting the script in dry-run mode:
.. code-block:: shell
/opt/bastion/bin/admin/osh-encrypt-rsync.pl --dry-run
Configuring keys, accounts & groups remote backup
=================================================
Everything that is needed to restore a bastion from backup (keys, accounts, groups, etc.) is backed up daily in ``/root/backups`` by default. If you followed the "Setup the encryption & signature GPG keys" section above, these backups will be encrypted automatically.
If you want to push these backups to a remote location, which is warmly advised, you have to specify the remote location to ``scp`` the backup archives to. The configuration file is ``/etc/bastion/osh-backup-acl-keys.conf``, and you should specify the ``PUSH_REMOTE`` and ``PUSH_OPTIONS``.
To verify that the script is correctly able to connect remotely (and also validate the remote hostkey), start the script manually:
.. code-block:: shell
:emphasize-lines: 1
/opt/bastion/bin/admin/osh-backup-acl-keys.sh
Pushing backup file (/root/backups/backup-2020-05-25.tar.gz.gpg) remotely...
backup-2020-05-25.tar.gz.gpg
100% 21MB 20.8MB/s 00:00
Also verify that the extension is ``.gpg``, as seen above, which indicates that the script successfully encrypted the backup.
Logs/Syslog
===========
It is advised to use syslog for The Bastion application logs. This can be configured in ``/etc/bastion/bastion.conf`` with the parameter ``enableSyslog``.
There is a default ``syslog-ng`` configuration provided, if you happen to use it. The file can be found as ``etc/syslog-ng/conf.d/20-bastion.conf.dist`` in the repository. Please read the comments in the file to know how to integrate it properly in your system.
Clustering (High Availability)
==============================
The bastions can work in a cluster, with N instances. In that case, there is one *master* instance, where any modification command can be used (creating accounts, deleting groups, granting accesses), and N-1 *slave* instances, where only *readonly* actions are permitted. Note that any instance can be used to connect to infrastructures, so in effect all instances can always be used at the same time. You may set up a DNS round-robin hostname, with all the instances IPs declared, so that clients automatically choose a random instance, without having to rely on another external component such as a load-balancer. Note that if you do this, you'll need all the instances to share the same SSH host keys.
Setting up a slave bastion
**************************
Before, setting up the slave bastion, you should have the two bastions up and running (follow the normal installation documentation).
On the slave
------------
The sync of the ``passwd`` and ``group`` files can have adverse effects on a newly installed machine where the packages where not installed in the same order than on the master, hence having different UIDs for the same users. The following commands are known to fix all the problems that could arise in that case, on an classic Debian machine, that has ``puppet``, ``postfix``, ``ossec`` and ``bind`` installed (disregard any *file or directory not found* message):
.. code-block:: shell
chown -R puppet:puppet /var/lib/puppet /var/log/puppet /run/puppet
chgrp puppet /etc/puppet
chown -R postfix /var/spool/postfix /var/lib/postfix
chown root:root /var/spool/postfix
chown -R root:root /var/spool/postfix/{pid,etc,lib,dev,usr}
chgrp -R postdrop /var/spool/postfix/{public,maildrop}
chown root:postdrop /usr/sbin/postdrop /usr/sbin/postqueue
chmod g+s /usr/sbin/postdrop /usr/sbin/postqueue
chown -R ossec /var/ossec/logs /var/ossec/queue /var/ossec/stats /var/ossec/var
chgrp -R ossec /var/ossec
chown ossecr /var/ossec/queue/agent-info /var/ossec/queue/rids
chown root /var/ossec/queue/ /var/ossec/queue/alerts/execq /var/ossec/var /var/ossec/var/run
chgrp bind /var/cache/bind /var/lib/bind /etc/bind /etc/bind/named.conf.default-zones /run/named
chown -R bind:bind /etc/bind/rndc.key /run/named
chgrp allowkeeper /var/log/bastion
Then, on the slave, set the ``readOnlySlaveMode`` option in the ``/etc/bastion/bastion.conf`` file to ``1``:
.. code-block:: shell
vim /etc/bastion/bastion.conf
This will instruct the bastion to deny any modification plugin, so that changes can only be done through the master instance.
Then, append the master bastion synchronization public SSH keyfile, found in ``~root/.ssh/id_master2slave.pub`` on the master instance, to ``~bastionsync/.ssh/authorized_keys`` on the slave, with the following prefix: ``from="IP.OF.THE.MASTER",restrict``
Hence the file should look like this:
``from="198.51.100.42",restrict ssh-ed25519 AAA[...]``
Note that if you're using an old OpenSSH before version 7.2, the prefix should be instead: ``from="IP.OF.THE.MASTER",no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty,no-user-rc``.
On the master
-------------
- Check that the key setup works correctly by launching the following command under the ``root`` account:
.. code-block:: shell
rsync -vaA --numeric-ids --dry-run --delete --filter "merge /etc/bastion/osh-sync-watcher.rsyncfilter" --rsh "ssh -i /root/.ssh/id_master2slave" / bastionsync@IP.OF.THE.SLAVE:/
- Check that it's not trying to rsync too much stuff (if you have weird things in your ``/home``, you might want to edit ``/etc/bastion/osh-sync-watcher.rsyncfilter`` to exclude that stuff)
- Once you're happy with the output, retry without the ``--dry-run``
- When it's done, run it immediately again to ensure it still work, because ``/etc/passwd`` and ``/etc/group`` will have been overwritten on the slave
- Then, edit the configuration on the master:
.. code-block:: shell
vim /etc/bastion/osh-sync-watcher.sh
- Then, configure the script to start on boot and start it manually:
.. code-block:: shell
systemctl enable osh-sync-watcher
systemctl start osh-sync-watcher
- You can check the logs (if you configured ``syslog`` instead, which is encouraged, then the logfile depends on your syslog daemon configuration)
.. code-block:: shell
tail -F /var/log/bastion/osh-sync-watcher.log
Misc
====
Fix buggy ReadLine under Debian Jessie
**************************************
Unfortunately, the version of `libterm-readline-gnu-perl` of Debian Jessie is bugged.
The version of Wheezy (7) and Stretch (9) are correct, only Jessie (8) is affected.
This impacts the ``interactive`` mode of the bastion, namely the autocomplete feature, if you want to apply a quickfix on your system, you can use this:
.. code-block:: shell
patch -p0 -d / -r - < /opt/bastion/contrib/libterm-readline-gnu-perl-jessiefix.patch
Now, as Debian Jessie is quite old, the proper solution is probably not to use it!
Create SSHFP records
********************
If you want to use ``SSHFP`` (for a bastion, you should), generate the records and publish them in the DNS:
.. code-block:: shell
awk 'tolower($1)~/^hostkey$/ {system("ssh-keygen -r bastion.name -f "$2)}' /etc/ssh/sshd_config
Harden the SSH configuration
****************************
You can use this script:
.. code-block:: shell
/opt/bastion/bin/admin/check-ssh-hardening.pl
Note that this script doesn't check everything, just a few items. If you want a complete audit of your SSH configuration, there are other tools available. Using our SSH templates is also a good start.
The script also supports generating custom moduli for your installation. The following command will generate moduli of 8192 bits size. Note that it'll take several hours:
.. code-block:: shell
/opt/bastion/bin/admin/check-ssh-hardening.pl --generate-moduli 8192
2FA root authentication
***********************
The bastion supports TOTP (Time-based One Time Password), to further secure high profile accesses. This section covers the configuration of 2FA root authentication on the bastion itself. TOTP can also be enabled for regular bastion users, but this is covered in another section. To enable 2FA root authentication, run on the bastion:
.. code-block:: shell
script -c "google-authenticator -t -Q UTF8 -r 3 -R 15 -s /var/otp/root -w 2 -e 4 -D" /root/qrcode
Of course, you can check the ``--help`` and adjust the options accordingly. The example given above has sane defaults, but you might want to adjust if needed.
Now, flash this QR code with your phone, using a TOTP application. You might want to copy the QR code somewhere safe in case you need to flash it on some other phone, by exporting the ``base64`` version of it:
.. code-block:: shell
gzip -c /root/qrcode | base64 -w150
Copy this in your password manager (for example). You can then delete the ``/root/qrcode`` file.
You have then two configuration adjustments to do.
- First, ensure you have installed the provided ``/etc/pam.d/sshd`` file, or at least the corresponding line to enable the TOTP pam plugin in your configuration.
- Second, ensure that your ``/etc/ssh/sshd_config`` file calls PAM for root authentication. In the provided templates, there is a commented snippet to do it. The uncommented snippet looks like this:
.. code-block:: shell
# 2FA has been configured for root, so we force pubkey+PAM for it
Match User root
AuthenticationMethods publickey,keyboard-interactive:pam
Note that first, the usual publickey method will be used, then control will be passed to PAM. This is where the ``/etc/pam.d/sshd`` configuration will apply.
Now, you should be asked for the TOTP the next time you try to login through ssh as root.
In case something goes wrong with the new configuration, be sure to keep your already opened existing connection to be able to fix the problem without falling back to console access.
Once this has been tested, you can (and probably should) also protect the direct root console access to your machine with TOTP, including a snippet similar to this one:
.. code-block:: shell
# TOTP config
auth [success=1 default=ignore] pam_google_authenticator.so secret=/var/otp/${USER}
auth requisite pam_deny.so
# End of TOTP Config
inside your ``/etc/pam.d/login`` file.
Of course, when using TOTP, this is paramount to ensure your server is properly synchronized through NTP.