#!/usr/bin/env bash
LAYEROPS_USER=layerops
LAYEROPS_GROUP=$LAYEROPS_USER
LAYEROPS_HOME_DIR=/home/layerops
LAYEROPS_BIN_DIR=${LAYEROPS_HOME_DIR}/bin
LAYEROPS_ETC_DIR=/etc/layerops
LAYEROPS_UFW_SCRIPT_PATH=/usr/local/bin/ly-ufw-update.sh
LAYEROPS_SCRIPT_PATH=/usr/local/bin/layerops
SUDO_FILE=/etc/sudoers.d/99-layerops-users
LAYEROPS_ROOT_DIR=/data/layerops
VGNAME=layerops
LVNAME=data
UFW_APPNAME=Layerops
UFW_APPFILE=/etc/ufw/applications.d/layerops
LXC_BRIDGE_DEVICE=lxdbr0
WIREGUARD_UDP_PORT=51820

function usage {
  cat << EOF
Usage: $(basename "${BASH_SOURCE[0]}") [init|clean]
EOF
  exit 0
}

function check_envvars() {
  MISSING=""
  for envvar in LAYEROPS_SCRIPT_URL
  do
    [ -z "${!envvar}" ] && MISSING="$envvar $MISSING"
  done

  if [ ! -z "$MISSING" ]
  then
    echo "Missing following environment variables:"
    for var in $MISSING
    do
      echo "  $var"
    done
    exit 1
  fi
}

function _init() {
  # Install required packages
  while fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1; do sleep 1; done;
  while fuser /var/lib/apt/lists/lock >/dev/null 2>&1; do sleep 1; done;
  apt-get update && apt-get install -y coreutils jq lvm2 ufw ipcalc-ng || exit 1

  # Get layerops run script
  wget -O $LAYEROPS_SCRIPT_PATH ${LAYEROPS_SCRIPT_URL}
  chmod 755 $LAYEROPS_SCRIPT_PATH

  # Create layerops user
  id $LAYEROPS_USER > /dev/null 2>&1 || adduser -q --gecos "" --disabled-password --home $LAYEROPS_HOME_DIR $LAYEROPS_USER
  mkdir -p $LAYEROPS_HOME_DIR/.ssh
  touch $LAYEROPS_HOME_DIR/.ssh/authorized_keys
  chown -R $LAYEROPS_USER:$LAYEROPS_GROUP $LAYEROPS_HOME_DIR

  # Set sudo access to layerops user
  cat > $SUDO_FILE <<EOF
# Group rules for layerops
%layerops ALL=(ALL) NOPASSWD: ALL
EOF

  # Create volumes if available
  FS_TYPE=ext4
  FSTAB_OPTIONS=defaults
  FSTAB_FILE=/etc/fstab

  mkdir -p $LAYEROPS_ROOT_DIR

  DEVICE=$(lsblk --json | jq -r '[.blockdevices[] | select(.type == "disk") | select(.children == null)]  | first | .name')
  if [[ ! -z "$DEVICE" && "$DEVICE" != "null" ]]
  then
    DISK=/dev/$DEVICE

    pvcreate $DISK
    vgcreate $VGNAME $DISK
    LV_SIZE=$(vgs --reportformat=json --units B $VGNAME | jq -r '.report[].vg[].vg_free' | tr '<' ' ')
    lvcreate -L $LV_SIZE -n $LVNAME $VGNAME

    PARTITION=/dev/${VGNAME}/${LVNAME}
    mkfs.$FS_TYPE -F $PARTITION

    echo "MOUNT $LAYEROPS_ROOT_DIR on $PARTITION"
    FSTAB_LINE="$PARTITION $LAYEROPS_ROOT_DIR $FS_TYPE $FSTAB_OPTIONS 0 2"
    grep -q "^$PARTITION" $FSTAB_FILE && sed "s=^${PARTITION}.*=$FSTAB_LINE=" -i $FSTAB_FILE || echo "$FSTAB_LINE" >>  $FSTAB_FILE

    mount $LAYEROPS_ROOT_DIR
  fi

  # Init firewall Config
  sed -i 's/IPV6=yes/IPV6=no/' /etc/default/ufw
  echo y | ufw enable
  ufw allow 22/tcp
  ufw route allow out on $LXC_BRIDGE_DEVICE from any to any proto udp port $WIREGUARD_UDP_PORT
  ufw allow in on $LXC_BRIDGE_DEVICE
  ufw route allow in on $LXC_BRIDGE_DEVICE

  cat > $UFW_APPFILE <<EOF
[${UFW_APPNAME}]
title=Layerops Orchestrator
description=Layerops Orchestrator ports to be opened to job provisionner
ports=22,80,443,4646,8501,9888,8200,9107/tcp
EOF

  mkdir -p $LAYEROPS_ETC_DIR
  cat > $LAYEROPS_UFW_SCRIPT_PATH <<EOF
#!/bin/bash
set -e
APPNAME=${UFW_APPNAME}
API_URL=${API_URL}
IPFILE=${LAYEROPS_ETC_DIR}/allowed_ips
TMPIPFILE=/tmp/allowed_ips
LXC_BRIDGE_DEVICE=${LXC_BRIDGE_DEVICE}

EOF

  cat >> $LAYEROPS_UFW_SCRIPT_PATH <<'EOF'
curl -A Nimeops-UA $API_URL/v1/config/publicIps | jq -r '.ips[]' > $TMPIPFILE
[ -z "$(cat $TMPIPFILE)" ] && exit 1
mv $TMPIPFILE $IPFILE

IFS=$'\n'
for rule in $(ufw status | grep "ALLOW FWD" |grep $APPNAME)
do
  IP=$(echo $rule | awk '{print $NF}')
  [ "$IP" == "Anywhere" ] && IP=any
  grep $IP $IPFILE >/dev/null || ufw route delete allow out on $LXC_BRIDGE_DEVICE from $IP to any app "$APPNAME"
done

for IP in $(cat $IPFILE); do
  ufw route allow out on $LXC_BRIDGE_DEVICE from $IP to any app "$APPNAME"
done
EOF

  chmod 755 $LAYEROPS_UFW_SCRIPT_PATH

  cat > /etc/systemd/system/ly-update-allowed-ips.service <<EOF
[Unit]
Description=Update IP allowed to access

[Service]
Type=oneshot
ExecStart=$LAYEROPS_UFW_SCRIPT_PATH
StandardOutput=journal

[Install]
WantedBy=multi-user.target
EOF

  cat > /etc/systemd/system/ly-update-allowed-ips.timer <<EOF
[Unit]
Description=Update IP allowed to access

[Timer]
OnBootSec=1m
OnUnitActiveSec=1m

[Install]
WantedBy=timers.target
EOF

  systemctl daemon-reload
  systemctl start ly-update-allowed-ips.service
  systemctl enable --now ly-update-allowed-ips.timer
}


function _clean() {
  # Remove layerops sudo config
  rm -f $SUDO_FILE

  # delete layerops user
  id $LAYEROPS_USER > /dev/null 2>&1 && userdel $LAYEROPS_USER

  # Clean files
  rm -fR $LAYEROPS_HOME_DIR $LAYEROPS_ROOT_DIR
}

if [[ "$#" -eq 0 ]]; then
  usage
fi

case "$1" in
  init)
    check_envvars
    _init
    ;;
  clean)
    _clean;;
  *)
    usage;;
esac
