#!/bin/bash

# Prepare a freshly-installed system with bcfg2
# Automates the "bcfg2-install; bcfg2 -qve; bcfg2-cleanup" procedure

V=0.50  # initial
V=0.51  # be BASH compliant
V=0.52  # remove bcfg2-install since it just causes headaches; bcfg2 -qve installs packages just fine
V=0.63  # add flock locking and more clear error messages
V=0.64  # cleanup legacy System-V files on SOE5

# Ensure we're root
if [ "$( whoami )" != "root" ]; then
        echo "Run this script as root."
        exit 1
fi

# Set up lock dir
if [[ -d /run/lock ]]; then
    LOCKFILE="/run/lock/system-prepare.lock"
else
    LOCKFILE="/tmp/system-prepare.lock"
fi

# Acquire a lock; wait 15 minutes to ensure time for a previous run to complete if needed
(
flock --exclusive --wait 900 200

# Ensure this is the first run
if [[ -f /usr/local/etc/bcfg2.bootstrapped ]]; then
        echo "System has already been prepared."
        exit 0
fi

echo "--------------------------------------------------------"
echo "BEGINNING SYSTEM PREPARE at $(date)"
echo "--------------------------------------------------------"

fail() {
    set +o xtrace

    # Remove policy-rc.d override (in case we didn't get that far)
    rm -f /usr/sbin/policy-rc.d || true

    echo "-------------------------------------------------------"
    echo "FAILURE: $@"
    echo "ABORTING SYSTEM PREPARE at $(date)"
    echo "-------------------------------------------------------"
    exit 1
}

set -o xtrace

source '/etc/os-release'

# Set path
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

# Set rw if needed (from system-update)
test -x /usr/local/sbin/rw && /usr/local/sbin/rw

# Ensure gawk is the active awk; otherwise add it
if [[ $( readlink /etc/alternatives/awk ) != '/usr/bin/gawk' ]]; then
    apt-get install --yes gawk
    update-alternatives --set awk /usr/bin/gawk
fi

# For wireshark-common, override the dpkg selection
#   "Capture packets as non-superuser" -> NO
# Prevents a non-interactive prompt during bcfg2-install
echo "wireshark-common wireshark-common/install-setuid boolean false" \
| debconf-set-selections

# Disable service startups during initial install (to prevent apt errors for unconfig'd services)
cat <<EOF >/usr/sbin/policy-rc.d
#!/bin/sh
exit 101
EOF
chmod +x /usr/sbin/policy-rc.d

# For noms43 hosts going forward, create the "splitdb" trigger entry
if [[ $( hostname -s ) == noms43 ]]; then
    mkdir -p /etc/noms
    echo "splitdb" | tee /etc/noms/type
fi

# Fix the OpenSSL bug in Debian Buster (first pass)
if [[ -f /etc/ssl/openssl.cnf ]]; then
    if grep -q 'SECLEVEL=2' /etc/ssl/openssl.cnf; then
        sed -i 's/DEFAULT@SECLEVEL=2/DEFAULT@SECLEVEL=1/g' /etc/ssl/openssl.cnf
    fi
fi

# Perform bcfg2 setup (bcfg2+apt bundles only)
/usr/sbin/bcfg2 -qve -b bcfg2-client:apt || fail "initial bcfg2 -qve -b bcfg2-client:apt"

# Fix the OpenSSL bug in Debian Buster (second pass)
if grep -q 'SECLEVEL=2' /etc/ssl/openssl.cnf; then
    sed -i 's/DEFAULT@SECLEVEL=2/DEFAULT@SECLEVEL=1/g' /etc/ssl/openssl.cnf
fi

# Perform bcfg2 setup
/usr/sbin/bcfg2 -qve || fail "initial bcfg2 -qve"

# Fix some backuppc errors here
if [[ $( hostname -s ) == backup ]]; then
    sudo -u backuppc mkdir -p /srv/backuppc/{pc,cpool}
fi

# Perform an apt update and upgrade
/usr/bin/apt-get update
/usr/bin/apt-get upgrade -y

# Perform bcfg2 setup again
/usr/sbin/bcfg2 -qve || fail "second bcfg2 -qve"

# Purge init separately or it freaks out
if [[ $VERSION_ID -ge 12 ]]; then
    # Use the new APT 1.1 flags instead of "Yes, do as I say!"
    apt-get purge --allow-remove-essential --yes init || fail "init purge"
else
    echo "Yes, do as I say!" | apt-get purge init || fail "init purge"
fi

# Clean up spurious packages (don't prompt)
/usr/local/sbin/bcfg2-cleanup --list | grep -v '=' | DEBIAN_FRONTEND=noninteractive xargs apt-get purge -y --force-yes || fail "initial bcfg2-cleanup"

# Remove policy-rc.d override
rm -f /usr/sbin/policy-rc.d

# Remove incorrectly applied ladvd and cryptdisks initscripts
rm -f /etc/init.d/cryptdisks /etc/init.d/ladvd

# Perform bcfg2 setup once more with *feeling*
/usr/sbin/bcfg2 -qve || fail "third bcfg2 -qve"

# Perform bcfg2 cleanup once more with *feeling*
/usr/local/sbin/bcfg2-cleanup --list | grep -v '=' | DEBIAN_FRONTEND=noninteractive xargs apt-get purge -y --force-yes || fail "second bcfg2-cleanup"

# Check for dhparams
if [[ -x /etc/cron.daily/dhparam-regenerate && ! -f /etc/ssl/dhparam.pem ]]; then
    # SOE4.x
    /etc/cron.daily/dhparam-regenerate
elif [[ -x /usr/local/sbin/dhparam-regenerate && ! -f /etc/ssl/dhparam.pem ]]; then
    # SOE5
    /usr/local/sbin/dhparam-regenerate
fi


# Run per-profile actions
case "$( hostname -s | tr -d '[0-9]*' )" in
    noms)
        # Only applicable on non-proxy noms43
        if [[ -x /usr/local/sbin/noms-symlinks ]]; then
            /usr/local/sbin/noms-symlinks || fail "noms-symlinks"
        fi
    ;;
    nomsdb)
        /usr/local/sbin/db-symlinks || fail "db-symlinks"
    ;;
    mail)
        touch /etc/postfix/local/inactive_access
        /usr/local/sbin/userhome_inactive-scan || fail "userhome_inactive-scan"
        /usr/bin/newaliases
    ;;
esac

# Run cert-download if present
if [[ -x /usr/local/sbin/le-cert-download ]]; then
    /usr/local/sbin/le-cert-download primary
fi

# Run letsencrypt-init if present
if [[ -x /usr/local/sbin/letsencrypt-init ]]; then
    /usr/local/sbin/letsencrypt-init
fi

# Run a2profile if present
if [[ -f /etc/apache2/profile ]]; then
    a2dismod php7.3
    a2dismod mpm_prefork
    a2dismod mpm_event
    /usr/local/sbin/a2profile
    service apache2 restart
fi

# Clean up dpkg-dist and dpkg-old files
find /etc -type f -name '*.dpkg-dist' -exec rm {} \;
find /etc -type f -name '*.dpkg-old' -exec rm {} \;

# One final cleanup
/usr/local/sbin/bcfg2-cleanup --list | grep -v '=' | DEBIAN_FRONTEND=noninteractive xargs apt-get purge -y --force-yes || fail "second bcfg2-cleanup"
dpkg -l | grep -v '^ii' | grep '^[a-z]' | awk '{ print $2 }' | DEBIAN_FRONTEND=noninteractive xargs apt-get purge -y --force-yes || fail "rc package cleanup"

# Check and fix service-init
/usr/local/sbin/syscheck check service-init
/usr/local/sbin/sysfix fix service-init

# Upload to inventory
/usr/local/sbin/inventory upload

# Update munin
/usr/local/sbin/update-munin-node || fail "munin update"

# Reinstall munin-plugins-core to fix invalid checksum on sensors_ plugin
/usr/bin/apt install --reinstall munin-plugins-core

# Update admin users and authorized keys, *just in case* something somehow went bad with bcfg2 earlier
/usr/local/sbin/update-admin_users || fail "update-admin_users"
/usr/local/sbin/update-authorized_keys || fail "update-authorized_keys"

# Fix logstash file ownerships (defaults to 777, correct to 775)
if [[ -d /usr/share/logstash/vendor/bundle ]]; then
    /bin/chmod --recursive o-w /usr/share/logstash/vendor/bundle
fi

# Update grub if present
if [[ -f /etc/default/grub ]]; then
    update-grub
fi

# Enable bcfg2-cron
/usr/local/sbin/bcfg2-cron enable

# Perform one final bcfg2 setup
/usr/sbin/bcfg2 -qve || fail "fourth bcfg2 -qve"

# Create the bootstrapped flag file
echo $( date +%s ) > /usr/local/etc/bcfg2.bootstrapped
echo "Done. Reboot the system now to complete setup."
echo "--------------------------------------------------------"
echo "COMPLETED SYSTEM PREPARE at $(date)"
echo "--------------------------------------------------------"

) 200>${LOCKFILE}
