#! /bin/bash

SCRIPT_VERSION='0.2.1'

VENDOR_IDENTIFIER='osgw'

JUMPER_USER='jumphost'
JUMPER_USER_COMMENT='Jumphost Framework Network Service'

JUMPHOST_PUB_KEY='ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA0IvAkT0Uihg1bJkTZTMrCqYx75Qst34Rw1Er7Bl3HK Framework Service Jumphost'
JUMPHOST_PRIV_KEY='U2FsdGVkX1/3unhKd/h2j3At1OCkZ5Xns5wYqqJSxrFUo69t6HPfbzR2sghmPDlK
[payload removed: 512 characters in 8 lines]
LZRUB/GRcbLD1msMzxr7wg=='

MANAGING_SSH_PUBKEYS='ssh-rsa [payload removed: 712 characters] SSH Javanaut Dev
ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBErKfanC6v1C8y+dTWUt5ZbgCPLn0ZCja69l80I/nDA1As4O5G+Af6lYQxvhV6R5BHjuHqOsGxXFDXN6+9k/cFS9TJkWiI5ZvR1vyQgE1AFEnBcDcA/x/d6EM3O8p4B5sA== SSH Carbonara host
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAJcLS0LtWj3/OusuniBOOquyR8dW74ZVrtfujqIyqGm SSH Ansible Control'

KEYBOARD_LOCALE='de'

TEXT_RED='\033[0;31m'
TEXT_GREEN='\033[0;32m'
TEXT_BLUE='\033[0;34m'
TEXT_WHITE='\033[0m'

if [[ ! -z $(uname -a | grep -E 'Debian|Ubuntu') ]]; then
  export DEBIAN_FRONTEND=noninteractive
  export DEBIAN_PRIORITY=critical
fi

updateSystem() {

    echo -n "Updating system ... "

    if [[ ! -z $(uname -a | grep MANJARO) ]]; then

      pacman -Syu base-devel git
      mkdir -p "/usr/local/osgw/src"
      pushd "/usr/local/osgw/src"
      git clone https://github.com/puxplaying/maus.git
      pushd maus
      makepkg -srci
      popd
      popd
      maus

    fi

    if [[ ! -z $(uname -a | grep -E 'Debian|Ubuntu') ]]; then

      apt-get -yqq update
      apt-get -yqq upgrade

      update-ca-certificates 1>/dev/null
    fi

    printf "${TEXT_GREEN}ok${TEXT_WHITE}\n"
}

installBasicPackages() {

    echo -n "Installing basic packages ... "

    if [[ ! -z $(uname -a | grep MANJARO) ]]; then
      pacman -S \
      acl \
      nano \
      git \
      curl \
      tar \
      expect \
      openssh \
      bison \
      debugedit \
      fakeroot \
      flex \
      gc \
      groff \
      guile \
      make \
      patch \
      pkgconf \
      texinfo \
      binutils \
      gcc \
      jansson \
      libisl \
      libmpc \
      libtool \
      autoconf \
      automake \
      diffutils \
      unzip \
      gzip \
      bzip2 \
      xz \
      python \
      which \
      python-pip \
      python-wheel \
      python-setuptools \
      python-requests \
      python-packaging \
      python-lxml \
      python-virtualenv \
      1>/dev/null
    fi

    if [[ ! -z $(uname -a | grep -E 'Debian|Ubuntu') ]]; then
      apt-get -yqq install \
      acl \
      apt-transport-https \
      build-essential \
      autoconf \
      automake \
      gpg-agent \
      openssh-server \
      nano \
      screen \
      git \
      curl \
      wget \
      expect \
      dirmngr \
      haveged \
      rng-tools \
      unzip \
      libbz2-dev \
      liblzma-dev \
      logrotate \
      ca-certificates \
      python3 \
      python3-pip \
      python3-dev \
      python3-wheel \
      python3-setuptools \
      python3-requests \
      python3-packaging \
      python3-lxml \
      python3-apt \
      python3-venv \
      python3-virtualenv \
      1>/dev/null
    fi

    printf "${TEXT_GREEN}ok${TEXT_WHITE}\n"
}

createManagementAccount() {

    echo -n "Creating managing user ... "

    if [[ -z "${MANAGING_HOME}" ]]; then
        MANAGING_HOME="/home/${MANAGING_USER}"
    fi

    managingUserId=$(id -u ${MANAGING_USER} 2>/dev/null)

    if [[ -z "${managingUserId}" ]]; then

      mkdir -p $(dirname "${MANAGING_HOME}")
      useradd -s /bin/bash -c "${VENDOR_IDENTIFIER^^}" -G sudo -m -d "${MANAGING_HOME}" "${MANAGING_USER}"
      chmod -R u=rwX,g=rX,o= "${MANAGING_HOME}"

      chown -R "${MANAGING_USER}:${MANAGING_USER}" "${MANAGING_HOME}"

      printf "${TEXT_GREEN}ok${TEXT_WHITE}\n"
    else
      printf "${TEXT_BLUE}exists${TEXT_WHITE}\n"
    fi
}

setupManagementAccount(){

      echo -n "Setting up managing user ... "

      mkdir -p "${MANAGING_HOME}/.ansible/tmp"
      mkdir -p "${MANAGING_HOME}/.tmp"
      mkdir -p "${MANAGING_HOME}/.local/src"

      chmod -R u=rwX,g=rX,o= "${MANAGING_HOME}"
      chmod -R u=rwX,g=,o= "${MANAGING_HOME}/.ansible"
      chown -R "${MANAGING_USER}:${MANAGING_USER}" "${MANAGING_HOME}/.ansible"
      chown -R "${MANAGING_USER}:${MANAGING_USER}" "${MANAGING_HOME}/.tmp"
      chown -R "${MANAGING_USER}:${MANAGING_USER}" "${MANAGING_HOME}/.local"

      mkdir -p "${MANAGING_HOME}/.ssh"
      chmod 700 "${MANAGING_HOME}/.ssh"
      echo "${MANAGING_SSH_PUBKEYS}" > "${MANAGING_HOME}/.ssh/authorized_keys"
      chmod 600 "${MANAGING_HOME}/.ssh/authorized_keys"
      chown -R "${MANAGING_USER}:${MANAGING_USER}" "${MANAGING_HOME}/.ssh"

      printf "${TEXT_GREEN}ok${TEXT_WHITE}\n"
}

generateModifiedBashRc() {

      echo -n "Generating modified .bashrc ... "

      [[ ! -f "${MANAGING_HOME}/.bashrc" ]] && cp /etc/skel/.bashrc "${MANAGING_HOME}/.bashrc"

      if [[ -z $(grep '#NON-INTERACTIVE' "${MANAGING_HOME}/.bashrc") ]]; then
          firstEmptyLine=$(grep -n -m 1 '^$' "${MANAGING_HOME}/.bashrc" | grep -Eo '[0-9]')
          sed -i "${firstEmptyLine}i
" "${MANAGING_HOME}/.bashrc"
          sed -i "${firstEmptyLine}i
" "${MANAGING_HOME}/.bashrc"
          sed -i "${firstEmptyLine}i\#NON-INTERACTIVE" "${MANAGING_HOME}/.bashrc"
          sed -i "${firstEmptyLine}i
" "${MANAGING_HOME}/.bashrc"
      fi

      if [[ -z $(grep '#INTERACTIVE' "${MANAGING_HOME}/.bashrc") ]]; then
          sed -i "\$a
" "${MANAGING_HOME}/.bashrc"
          sed -i "\$a\#INTERACTIVE" "${MANAGING_HOME}/.bashrc"
          sed -i "\$a
" "${MANAGING_HOME}/.bashrc"
      fi

      if [[ -z $(grep '#REMOVE DOUBLE PATHS' "${MANAGING_HOME}/.bashrc") ]]; then
          sed -i '/#NON-INTERACTIVE/a unset pathBuffer' "${MANAGING_HOME}/.bashrc"
          sed -i '/#NON-INTERACTIVE/a export PATH=$(n= IFS='"':'"'; for e in $pathBuffer; do [[ :$n == *:$e:* ]] || n+=$e:; done; echo "${n:0: -1}")' "${MANAGING_HOME}/.bashrc"
          sed -i '/#NON-INTERACTIVE/a [[ -n "${USER_PATH}" ]] && pathBuffer="${USER_PATH}:${PATH}"' "${MANAGING_HOME}/.bashrc"
          sed -i '/#NON-INTERACTIVE/a pathBuffer="$PATH"' "${MANAGING_HOME}/.bashrc"
          sed -i '/#NON-INTERACTIVE/a\#REMOVE DOUBLE PATHS' "${MANAGING_HOME}/.bashrc"
          sed -i '/#NON-INTERACTIVE/a
' "${MANAGING_HOME}/.bashrc"
          sed -i '/#NON-INTERACTIVE/a\#USER_PATH=' "${MANAGING_HOME}/.bashrc"
          sed -i '/#NON-INTERACTIVE/a
' "${MANAGING_HOME}/.bashrc"
          sed -i '/#NON-INTERACTIVE/a
' "${MANAGING_HOME}/.bashrc"
      fi

      sed -i 's/^[# ]*shopt -s globstar.*$/shopt -s globstar/' "${MANAGING_HOME}/.bashrc"
      sed -i 's/^[# ]*force_color_prompt.*$/force_color_prompt=yes/' "${MANAGING_HOME}/.bashrc"
      sed -i 's/^[# ]*export GCC_COLORS/export GCC_COLORS/' "${MANAGING_HOME}/.bashrc"

      printf "${TEXT_GREEN}ok${TEXT_WHITE}\n"
}

configureSystem() {

    echo -n "Configuring system ... "

    # Set keyboard layout
    sed -i -E "s/XKBLAYOUT=\"[a-z]{2}\"/XKBLAYOUT=\"${KEYBOARD_LOCALE}\"/" /etc/default/keyboard

    # Allow passwordless sudo
    if [[ "$SETUP_SHADOW_STORAGE" != 'yes' ]]; then
        sed -i 's/^%sudo.*$/%sudo        ALL=(ALL)       NOPASSWD: ALL/' /etc/sudoers
    fi

    # Add ssl certs path to environment file
    if [[ -z $(grep 'SSL_CERT_DIR' /etc/environment) ]]; then
        sed -i '$a\SSL_CERT_DIR="/etc/ssl/certs"' /etc/environment
    fi

    printf "${TEXT_GREEN}ok${TEXT_WHITE}\n"
}

configureSsh() {

    echo -n "Configuring SSH ... "

    # no|prohibit-password
    sed -i 's/^[# ]*PermitRootLogin.*$/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
    sed -i 's/^[# ]*PubkeyAuthentication.*$/PubkeyAuthentication yes/' /etc/ssh/sshd_config
    sed -i 's/^[# ]*PasswordAuthentication.*$/PasswordAuthentication no/' /etc/ssh/sshd_config
    sed -i 's/^[# ]*UseDNS.*$/UseDNS no/' /etc/ssh/sshd_config
    systemctl reload sshd

    printf "${TEXT_GREEN}ok${TEXT_WHITE}\n"
}

setHostname(){

    echo -n "Setting hostname ... "
    currentHostname=$(cat /etc/hostname)
    echo -n "${MANAGED_HOSTNAME}" > /etc/hostname
    sed -i "s/${currentHostname}/${MANAGED_HOSTNAME}/" /etc/hosts
    hostname -F /etc/hostname
    printf "${TEXT_GREEN}ok${TEXT_WHITE}\n"
}

setupFirewall() {

    echo -n "Enabling firewall ... "
    ufw logging on 1>/dev/null
    ufw allow 22/tcp 1>/dev/null
    ufw --force enable 1>/dev/null
    printf "${TEXT_GREEN}ok${TEXT_WHITE}\n"
}

setupJumperService() {

    if [[ ! -z ${2} ]]; then
      instanceSeparator='@'
      instanceSuffix="${2}"
      instancePlaceholder='%i'
    fi

    echo -n "Setting up Jtunnel to ${1} ... "
    cat > "/etc/default/jumper-tunnel${instanceSeparator}${instanceSuffix}" << EOF
REMOTE_URL=${1}
REMOTE_USER=${JUMPER_USER}
REMOTE_PORT=${JUMPER_PORT}
LOCAL_PORT=22
EOF

    cat > "/etc/systemd/system/jtunnel${instanceSeparator}.service" << EOF
[Unit]
Description=Setup jumper tunnel
After=network.target

[Service]
User=${MANAGING_USER}
EnvironmentFile=/etc/default/jumper-tunnel${instanceSeparator}${instancePlaceholder}
ExecStart=/usr/bin/ssh -NT -i "${MANAGING_HOME}/.ssh/ssh-jumphost" -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes -R \${REMOTE_PORT}:localhost:\${LOCAL_PORT} \${REMOTE_USER}@\${REMOTE_URL}

# Restart every >2 seconds to avoid StartLimitInterval failure
RestartSec=5
Restart=always

[Install]
WantedBy=multi-user.target
EOF

    echo "${JUMPHOST_PRIV_KEY}" > "${MANAGING_HOME}/.ssh/ssh-jumphost.aes"
    chown ${MANAGING_USER}:${MANAGING_USER} "${MANAGING_HOME}/.ssh/ssh-jumphost.aes"
    chmod 600 "${MANAGING_HOME}/.ssh/ssh-jumphost.aes"

    openssl aes-256-cbc -a -d -pbkdf2 -pass env:SSH_KEY_DECRYPTION_PASSWORD \
      -in "${MANAGING_HOME}/.ssh/ssh-jumphost.aes" -out "${MANAGING_HOME}/.ssh/ssh-jumphost"

    chmod 600 "${MANAGING_HOME}/.ssh/ssh-jumphost"
    chown ${MANAGING_USER}:${MANAGING_USER} "${MANAGING_HOME}/.ssh/ssh-jumphost"
    sed -i '$a
' "${MANAGING_HOME}/.ssh/ssh-jumphost"
    rm "${MANAGING_HOME}/.ssh/ssh-jumphost.aes"


    ssh-keyscan -H "${1}" >> "${MANAGING_HOME}/.ssh/known_hosts" 1>/dev/null 2>&1

    jumperIpv4=$(host "${1}" | awk '{ print $NF }' | head -1 | cat)
    [[ ! -z "${jumperIpv4}" ]] && ssh-keyscan -H ${jumperIpv4} >> "${MANAGING_HOME}/.ssh/known_hosts" 1>/dev/null 2>&1

    jumperIpv6=$(host "${1}" | awk '{ print $NF }' | tail -1 | cat)
    [[ ! -z "${jumperIpv6}" ]] && ssh-keyscan -H ${jumperIpv6} >> "${MANAGING_HOME}/.ssh/known_hosts" 1>/dev/null 2>&1

    chown "${MANAGING_USER}:${MANAGING_USER}" "${MANAGING_HOME}/.ssh/known_hosts"

    systemctl daemon-reload
    printf "${TEXT_GREEN}ok${TEXT_WHITE}\n"
}


setupShadowNode() {

    echo -n "Creating shadow lock and unlock scripts ... "

    mkdir -p "/usr/local/osgw/bin"
    chown root:root "/usr/local/osgw/bin"
    chmod 0755 "/usr/local/osgw/bin"

    touch "/usr/local/osgw/bin/shadow_unlock.sh"
    chown root:root "/usr/local/osgw/bin/shadow_unlock.sh"
    chmod 0755 "/usr/local/osgw/bin/shadow_unlock.sh"
    truncate -s0 "/usr/local/osgw/bin/shadow_unlock.sh"

    cat > "/usr/local/osgw/bin/shadow_unlock.sh" << EOF
#! /bin/bash

TEXT_RED='\033[0;31m'
TEXT_GREEN='\033[0;32m'
TEXT_BLUE='\033[0;34m'
TEXT_WHITE='\033[0m'

echo -n "Opening SSH firewall port ... "
ufw allow 22/tcp 1>/dev/null
printf "${TEXT_GREEN}ok${TEXT_WHITE}\n"

echo -n "Enabling SSH access for root ... "
sed -i 's/^[# ]*PermitRootLogin.*$/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
systemctl reload sshd
printf "${TEXT_GREEN}ok${TEXT_WHITE}\n"

EOF

    sed -i '/#INTERACTIVE/a alias shadow_unlock=/usr/local/osgw/bin/shadow_unlock.sh' "${MANAGING_HOME}/.bashrc"


    touch "/usr/local/osgw/bin/shadow_lock.sh"
    chown root:root "/usr/local/osgw/bin/shadow_lock.sh"
    chmod 0755 "/usr/local/osgw/bin/shadow_lock.sh"
    truncate -s0 "/usr/local/osgw/bin/shadow_lock.sh"

    cat > "/usr/local/osgw/bin/shadow_lock.sh" << EOF
#! /bin/bash

TEXT_RED='\033[0;31m'
TEXT_GREEN='\033[0;32m'
TEXT_BLUE='\033[0;34m'
TEXT_WHITE='\033[0m'

echo -n "Closing SSH firewall port ... "
ufw delete allow 22/tcp 1>/dev/null
printf "${TEXT_GREEN}ok${TEXT_WHITE}\n"

echo -n "Disabling SSH access for root ... "
sed -i 's/^[# ]*PermitRootLogin.*$/PermitRootLogin no/' /etc/ssh/sshd_config
systemctl reload sshd
printf "${TEXT_GREEN}ok${TEXT_WHITE}\n"

EOF

    sed -i '/#INTERACTIVE/a alias shadow_lock=/usr/local/osgw/bin/shadow_lock.sh' "${MANAGING_HOME}/.bashrc"


    printf "${TEXT_GREEN}ok${TEXT_WHITE}\n"
}


if [[ ! -z $SUDO_USER ]]; then
    MANAGING_USER=$SUDO_USER
    MANAGING_HOME=$(getent passwd $SUDO_USER | cut -d: -f6)
else
    MANAGING_USER=$USER
    MANAGING_HOME=$HOME
fi


jumphostUrls=()
while getopts 'vhaitwn:m:d:j:p:l:' opt; do
    case $opt in

        v)  echo "OSGW init.sh v${SCRIPT_VERSION}"
            exit 0;;
        h)  echo "OSGW init.sh v${SCRIPT_VERSION}"
            echo
            echo "usage:"
            echo
            echo "curl -s https://<Download URL>/init.sh | bash -s -- -a -i -m <Managing User> -d <Managing User Homedirectory> -n <Hostname> -p <Jumper Port> -j [<label>=]<jumphost_url>"
            echo
            echo "-a Update system"
            echo "-i Install basic packages"
            echo
            echo "-w Setup shadow storage node"
            echo
            exit 0;;

        a)  UPDATE_SYSTEM=yes;;
        i)  INIT_SYSTEM=yes;;

        n)  MANAGED_HOSTNAME="${OPTARG}";;

        m)  CREATE_MANAGING_USER=yes
            MANAGING_USER="${OPTARG}";;

        w)  CREATE_MANAGING_USER=yes
            SETUP_SHADOW_STORAGE=yes
            MANAGING_USER=root
            MANAGING_HOME=/root;;

        d)  MANAGING_HOME="${OPTARG}";;

        j)  CREATE_JUMPER_TUNNELS=yes
            if [[ "${OPTARG}" == *"="* ]]; then
              jumphostUrls+=("${OPTARG}")
            else
              JUMPHOST_URL="${OPTARG}"
            fi;;
        p)  JUMPER_PORT="${OPTARG}";;
        l)  KEYBOARD_LOCALE="${OPTARG}";;
    esac
done

shift "$OPTIND"
# Remaining params in "$@"


if [[ ! -z $UPDATE_SYSTEM ]]; then
  updateSystem
fi

if [[ ! -z $INIT_SYSTEM ]]; then
  installBasicPackages
  configureSystem
  configureSsh
  setupFirewall
fi

if [[ "$CREATE_MANAGING_USER" == 'yes' ]]; then
  [[ "$MANAGING_USER" != 'root' ]] && createManagementAccount
  setupManagementAccount
  generateModifiedBashRc
fi

if [[ ! -z $MANAGED_HOSTNAME ]]; then
  setHostname
fi

if [[ ! -z $CREATE_JUMPER_TUNNELS ]]; then

  read -sp 'Enter password for decrypting jumphost SSH key: ' SSH_KEY_DECRYPTION_PASSWORD </dev/tty
  export SSH_KEY_DECRYPTION_PASSWORD
  echo

  if [[ ${jumphostUrls[@]} ]]; then
    for jumphost in ${jumphostUrls[@]}; do
      setupJumperService "$(echo ${jumphost} | cut -d= -f2)" "$(echo ${jumphost} | cut -d= -f1)"
    done
  else
    setupJumperService "${JUMPHOST_URL}"
  fi

  unset SSH_KEY_DECRYPTION_PASSWORD

fi

if [[ $SETUP_SHADOW_STORAGE == 'yes' ]]; then
    setupShadowNode
fi
