provisioning tool for building opinionated architecture
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

294 lines
8.8 KiB

#!/bin/bash
### FUNCTIONS
### ---------
function prepare_config_hardened() {
mkdir -p "$HARDEN_CONFIGDIR"
}
function pubkey_authorize() {
local PREFIX="harden:pubkey:authorize"
if [[ ! -d $HOME/.ssh ]]; then
echo -n "create .ssh folder for the first time ..."
mkdir -m 700 ~/.ssh
PREFIX="" echo "OK"
else
local security_issue_in_ssh_folder
security_issue_in_ssh_folder=$(find "$HOME/.ssh" -perm -go=r | wc -l)
if [[ $security_issue_in_ssh_folder -gt 0 ]]; then
echo -n "force security in .ssh folder for <$CURRENT_USER> ..."
chmod -R u+rwX,go-rwx "/home/$CURRENT_USER/.ssh"
PREFIX="" echo "OK"
else
echo "security in .ssh folder for <$CURRENT_USER> approved!"
fi
fi
pubkey_value=$(yq ".authorized.pubkey" "$HARDEN_CONFIGFILE")
if [[ ! -f /home/$CURRENT_USER/.ssh/authorized_keys ]]; then
echo -n "authorized_keys first time ..."
PREFIX="" echo "$pubkey_value" >"$HOME/.ssh/authorized_keys"
chmod u+rw,go-rwx "/home/$CURRENT_USER/.ssh/authorized_keys"
PREFIX="" echo "OK"
else
if ! grep -q "^$pubkey_value" "/home/$CURRENT_USER/.ssh/authorized_keys"; then
echo -n "pubkey <$CURRENT_USER> appended to <.ssh/authorized_keys> ..."
echo "$pubkey_value" >>"$HOME/.ssh/authorized_keys"
PREFIX="" echo "OK"
else
echo "pubkey <$CURRENT_USER> already authorized!"
fi
fi
}
function sudoers() {
local PREFIX="harden:sudoers"
if [[ -d /etc/sudoers.d ]]; then
echo -n "add $CURRENT_USER and no more ..."
sudo env current_user="$CURRENT_USER" tera -e --env-key env --env-only -o /etc/sudoers -t "$MIAOU_BASEDIR/templates/hardened/sudoers.j2" >/dev/null
rm /etc/sudoers.d -rf
grep -Eq "^debian" /etc/passwd && userdel -rf debian
grep -Eq "^sudo" /etc/group && groupdel sudo
passwd -dq root
passwd -dq "$CURRENT_USER"
PREFIX="" echo "OK"
else
echo "sudo authorized for <$CURRENT_USER> only!"
fi
}
function sshd() {
local PREFIX="harden:sshd"
if [[ ! -f /etc/ssh/sshd_config ]]; then
sudo apt install -y openssh-server
else
echo "sshd already installed!"
fi
if ! grep -Eq "^Port 2222" /etc/ssh/sshd_config; then
echo -n "replacing sshd ..."
sudo env current_user="$CURRENT_USER" tera -e --env-key env --env-only -o /etc/ssh/sshd_config -t "$MIAOU_BASEDIR/templates/hardened/sshd_config.j2" >/dev/null
sudo systemctl restart sshd
PREFIX="" echo "OK"
else
echo "already done!"
fi
}
function prepare_proxy() {
local PREFIX="harden:proxy"
if ! grep -Eq "^precedence ::ffff:0:0/96.*" /etc/gai.conf; then
echo "prefer ipv4 ..."
sudo /opt/debian-bash/tools/append_or_replace "^precedence ::ffff:0:0/96.*" "precedence ::ffff:0:0/96 100" /etc/gai.conf
echo "OK"
else
echo "ipv4 already prefered!"
fi
if ! grep -Eq "^net.ipv4.ip_forward=1" /etc/sysctl.conf; then
echo "allow forwarding from kernel ..."
sudo /opt/debian-bash/tools/append_or_replace "^net.ipv4.ip_forward=1.*" "net.ipv4.ip_forward=1" /etc/sysctl.conf
sudo sysctl -p
echo "OK"
else
echo "kernel forwarding already allowed!"
fi
}
function set_current_user {
local PREFIX="harden:environment"
CURRENT_USER=$(id -un)
echo "current user is <$CURRENT_USER>"
}
function load_configuration {
local PREFIX="harden:configuration:load"
if [[ ! -f "$HARDEN_CONFIGFILE" ]]; then
echo "configuration requires further details ..."
cp "$MIAOU_BASEDIR/templates/hardened/hardened.yaml.sample" "$HARDEN_CONFIGFILE"
echo "OK"
fi
editor "$HARDEN_CONFIGFILE"
}
function check_configuration {
local PREFIX="harden:configuration:check"
check_yaml_defined_value "$HARDEN_CONFIGFILE" 'authorized.pubkey'
check_yaml_defined_value "$HARDEN_CONFIGFILE" 'alert.to'
check_yaml_defined_value "$HARDEN_CONFIGFILE" 'alert.from'
check_yaml_defined_value "$HARDEN_CONFIGFILE" 'alert.smtp.server'
}
function set_timezone_if_defined {
local PREFIX="harden:timezone"
timezone=$(yq ".timezone" "$HARDEN_CONFIGFILE")
if [[ "$timezone" != null ]]; then
if ! grep -q "$timezone" /etc/timezone; then
if [[ -f "/usr/share/zoneinfo/$timezone" ]]; then
echo "set timezone to $timezone ..."
ln -fs "/usr/share/zoneinfo/$timezone" /etc/localtime
dpkg-reconfigure -f noninteractive tzdata
echo OK
else
echoerr "unkown timezone: <$timezone>, please edit <$HARDEN_CONFIGFILE> and change to a correct value" && exit 98
fi
else
echo "timezone <$timezone> already set!"
fi
fi
}
function mailer_alert() {
local PREFIX="harden:mailer"
if [[ ! -f /etc/msmtprc ]]; then
for i in exim4-config libevent-2.1-7 libgnutls-dane0 libunbound8; do
if dpkg -l "$i" 2>/dev/null | grep -q ^ii && echo 'installed'; then
echo "purging package <$i> ..."
apt purge -y "$i"
echo "OK"
fi
done
echo "installing <msmtp> ..."
sudo /opt/debian-bash/tools/idem_apt_install msmtp msmtp-mta mailutils bsd-mailx
echo "OK"
echo "configuring </etc/aliases>"
sudo env current_user="$CURRENT_USER" tera -e --env-key env -o /etc/aliases -t "$MIAOU_BASEDIR/templates/hardened/mailer/aliases.j2" "$HARDEN_CONFIGDIR/hardened.yaml" >/dev/null
echo "OK"
# populate environment variable with fqdn
fqdn=$(hostname -f)
echo "configuring </etc/mail.rc>"
sudo env current_user="$CURRENT_USER" fqdn="$fqdn" tera -e --env-key env -o /etc/mail.rc -t "$MIAOU_BASEDIR/templates/hardened/mailer/mail.rc.j2" "$HARDEN_CONFIGDIR/hardened.yaml" >/dev/null
echo "OK"
echo "generating </etc/msmtprc> configuration file ..."
sudo env fqdn="$fqdn" tera -e --env-key env -o /etc/msmtprc -t "$MIAOU_BASEDIR/templates/hardened/mailer/msmtprc.j2" "$HARDEN_CONFIGDIR/hardened.yaml" >/dev/null
sudo chown root:msmtp /etc/msmtprc
sudo chmod 640 /etc/msmtprc
echo "OK"
else
echo "mailer <msmtp> already configured!"
fi
}
function alert_at_boot() {
local PREFIX="harden:alert:boot"
if ! systemctl is-enabled --quiet on_startup.service 2>/dev/null; then
echo "installing <on_startup.service> on systemd..."
sudo cp "$MIAOU_BASEDIR/templates/hardened/systemd/on_startup.service" /etc/systemd/system/on_startup.service
sudo systemctl daemon-reload
sudo systemctl enable on_startup.service
REBOOT=true
echo "OK"
else
echo "systemd <on_startup.service> already enabled!"
fi
}
function show_reboot_on_purpose() {
if "$REBOOT"; then
PREFIX="harden:reboot" echowarn "we recommend reboot on purpose, Reboot NOW?"
else
PREFIX="harden" echo "success"
fi
}
function disable_systemd_resolved() {
PREFIX="harden:systemd:resolved"
if file /etc/resolv.conf | grep -q /run/systemd/resolve/stub-resolv.conf; then
echo "disabling systemd-resolved..."
sudo systemctl stop systemd-resolved.service
sudo systemctl disable systemd-resolved.service
sudo rm /etc/resolv.conf
cat <<EOF | sudo tee /etc/resolv.conf
nameserver 1.1.1.1
EOF
echo "OK"
else
echo "systemd-resolved already disabled!"
fi
}
function alert_at_ssh_password() {
local PREFIX="harden:alert:ssh:password"
if ! grep -Eq "^session optional pam_exec.so /usr/local/bin/alert_ssh_password.sh" /etc/pam.d/sshd; then
echo "installing alert_at_ssh_password..."
sudo cp "$MIAOU_BASEDIR/templates/hardened/pam/alert_ssh_password.sh" /usr/local/bin/
sudo chmod 700 /usr/local/bin/alert_ssh_password.sh
sudo /opt/debian-bash/tools/append_or_replace "^session optional pam_exec.so /usr/local/bin/alert_ssh_password.sh" "session optional pam_exec.so /usr/local/bin/alert_ssh_password.sh" /etc/pam.d/sshd
echo "OK"
else
echo "alert_at_ssh_password already enabled!"
fi
}
function customize_motd {
local PREFIX="harden:motd:customize"
if [[ ! -f /etc/update-motd.d/80-users ]]; then
echo "customizing motd..."
sudo /opt/debian-bash/tools/idem_apt_install figlet lsb-release
sudo rm -f /etc/motd
sudo mkdir -p /etc/update-motd.d
sudo rm -f /etc/update-motd.d/*
sudo cp "$MIAOU_BASEDIR"/templates/hardened/motd/* /etc/update-motd.d/
sudo chmod +x /etc/update-motd.d/*
echo "OK"
else
echo "motd already customized!"
fi
}
### CONSTANTS
### ---------
MIAOU_BASEDIR=$(readlink -f "$(dirname "$0")/..")
readonly HARDEN_CONFIGDIR="$HOME/.config/hardened"
readonly HARDEN_CONFIGFILE="$HARDEN_CONFIGDIR/hardened.yaml"
### MAIN
### ----
# shellcheck source=/dev/null
. "$MIAOU_BASEDIR/lib/functions.sh"
miaou_init
REBOOT=false
PREFIX="harden"
: $PREFIX
sudo_required
install_debian_bash
install_mandatory_commands
prepare_config_hardened
set_current_user
check_configuration 2>/dev/null || load_configuration
check_configuration
pubkey_authorize
sshd
prepare_proxy
prepare_nftables
disable_systemd_resolved
set_timezone_if_defined
mailer_alert
alert_at_boot
alert_at_ssh_password
customize_motd
show_reboot_on_purpose