#!/bin/bash
# Automatisation de configuration backuppc pour poste linux
# Institut de Physique de Rennes UMR6251
# Anthony CARRÉ, Jérémy GARDAIS, Guillaume RAFFY — Mars 2016

SUCCESS=0
ERROR=1

function getDefaultUser() {
  case $(uname) in
    'Darwin')
      for user in $(ListUsers); do
        echo $user
        return
      done
      ;;
    'Linux')
      getent passwd "1000" | cut -d: -f1
      ;;
  esac
}


# this performs the equivalent as adding a remote login user in system preferences using the gui
function allowUserToConnectToThisMachineUsingSsh()
{
  local userLogin="$1"

  case $(uname) in
    'Darwin')
      dscl . append '/Groups/com.apple.access_ssh' user "${userLogin}"
      dscl . append /Groups/com.apple.access_ssh groupmembers $(dscl . read "/Users/${userLogin}" GeneratedUID | cut -d " " -f 2)
      ;;
    'Linux')
      # nothing to do?
      ;;
  esac
}

function ensureSshdIsRunning()
{
  case $(uname) in
    'Darwin')
      sudo launchctl list | grep 'com.openssh.sshd' &> /dev/null
      if [ $? != 0 ]; then
        # enable 'Remote login' in 'system preferences'
        launchctl load /System/Library/LaunchDaemons/ssh.plist &> /dev/null
      fi
      ;;
    'Linux')
      #if [ ! -f "${hostkey}" ]; then
      if [ ! $(command -v sshd) ]; then
        printf "\nopenssh-server non installé, tentative d’installation.\n"

        if hash apt 2>/dev/null;            then apt install -y openssh-server
          elif hash pacman 2>/dev/null;   then pacman -Syu openssh
          elif hash yum 2>/dev/null;      then yum install -y openssh-server
          elif hash zypper 2>/dev/null;   then zypper install openSSH
          else printf '\e[1;31m%-6s\e[m' "Merci d’installer openssh-server sur votre machine, installation annulée."; return "$ERROR"
        fi
        # Si ssh installé par le script, le restreindre à backuppc
        configssh="/etc/ssh/sshd_config"
        if [ ! -f "${configssh}" ]; then
          echo "AllowUsers backuppc" >> "${configssh}"
        fi
      fi

      ;;
  esac
}

function getMyHostKey() {
  local hostkey=''
  case $(uname) in
    'Darwin')
      hostkey="/etc/ssh_host_rsa_key.pub"
      if [ ! -f "${hostkey}" ]; then
        printf '\e[1;31m%-6s\e[m' "Impossible de trouver la clef ssh publique ce cette machine, installation annulée."
        return "$ERROR"
      fi
      ;;
    'Linux')
      hostkey="/etc/ssh/ssh_host_ecdsa_key.pub"
      #### SI MALGRÉ L’INSTALLATION DE OPENSSH, LA CLÉ N’EST TOUJOURS PAS ACCESSIBLE
      if [ ! -f "${hostkey}" ]; then
        return "$ERROR"
      fi
      # TODO : check that sshd is running ?
      ;;
  esac
  echo "${hostkey}"
}

function IpAddress() {
  local strMyIpAddress=''
  local strOsName=$( uname )
  case $strOsName in
    "Darwin")
      strMyIpAddress=$(dig +short myip.opendns.com @resolver1.opendns.com) ;;
    "Linux" )
      strMyIpAddress=$(wget http://checkip.dyndns.org/ -O - -o /dev/null | cut -d" " -f 6 | cut -d\< -f 1) ;;
    * )
      error "unhandled case ($strOsName)"
      return 1 ;;
  esac
  if [ "$strMyIpAddress" == '' ]; then
    error "failed to retrieve the ip address of this machine"
    return 1
  fi
  echo $strMyIpAddress
}

function MyFqdn() {
  local strMyIpAddress=$( IpAddress ) # eg '129.20.27.49'
  local strMyFqdn=$(host $strMyIpAddress | awk '{print $5}')
  echo ${strMyFqdn%?} # remove the trailing '.'
}

function ListUsers() {
  local users=''
  case $(uname) in
    'Darwin')
      for user in $(ls -d /Users/[a-zA-Z]*); do
        user=$(basename $user)
        case "$user" in
          'Shared'|'admin')
            ;;
          *)
            users="$users $user"
            ;;
        esac
      done
      ;;
    'Linux')    users="$(echo $(ls -I 'lost+found' -I 'administrateur' /home/) | sed -e 's/\///g')" ;;
  esac
  echo $users
}

function AddUserBackuppc() {
  local userToBackup="$1" # the login of the user to backup
  local homeDir="$2" # par exemple '/var/lib/backuppc'
  local userLogin='backuppc'
  local groupId=$(id -g $userToBackup)
  case $(uname) in
    'Darwin')
      maxid=$(dscl . -list /Users UniqueID | awk  '$2 < 1000 {print $2}' | sort -ug | tail -1)
      newid=$((maxid+1))
      mkdir -p "$homeDir"
      id "$newid" &> /dev/null
      if [ $? = 0 ]; then
        echo "unable to find a suitable uid for user backuppc ($newid is already used)"
        exit $ERROR
      fi
      dscl . -create "/Users/$userLogin"
      dscl . -create "/Users/$userLogin" UserShell /bin/bash
      dscl . -create "/Users/$userLogin" RealName "backuppc"
      dscl . -create "/Users/$userLogin" UniqueID "$newid"
      dscl . -create "/Users/$userLogin" PrimaryGroupID "$groupId"
      dscl . -create "/Users/$userLogin" NFSHomeDirectory "$homeDir"
      dscl . -create "/Users/$userLogin" IsHidden 1 # hide from login window
      #dscl . -passwd "/Users/$userLogin" password
        ;;
    'Linux') adduser --system --disabled-password --shell /bin/sh --home "$homeDir/" --gid "$groupId" "$userLogin" ;;
  esac
  chown -R "$userLogin:$groupId" "$homeDir"
  allowUserToConnectToThisMachineUsingSsh "${userLogin}"
}

#### VÉRIFIER QUE L’ON A BIEN LES DROITS ADMIN ####
if [ "$EUID" -ne 0 ]; then
  printf '\e[1;31m%-6s\e[m' "À lancer avec les droits administrateur "
  exit
fi

#### NOM DU COMPTE À SAUVEGARDER ####
default_user=$(getDefaultUser)
printf '\e[1;34m%-6s\e[m' "liste des comptes détectés sur cette machine :\n $(ListUsers)"
printf "\n"
printf "login de l’utilisateur dont les données sont à sauvegarder ?\n [${default_user}] : "
read input_login
if [[ ${input_login} != "" ]]; then
    usr="${input_login}"
    else usr="${default_user}"
fi

#### VÉRIFIER QUE LE COMPTE EST BIEN DANS LA LISTE DES USER ID ####
if ! id "${usr}" &> /dev/null; then
  printf '\e[1;35m%-6s\e[m' "${usr} n’apparait pas dans la liste des user ids. Continuer tout de même ? [o/N] : "
  read input_continue
  if [[ "${input_continue}" != "o" ]]; then
    printf '\e[1;31m%-6s\e[m' "Installation annulée."
    exit
  fi
fi

#### DOSSIER À SAUVEGARDER ####
default_dir=$(eval echo ~${usr})
if [ ! -d "${default_dir}" ]; then
    default_dir=""
fi
printf "Par défaut, le dossier sauvegardé est le home de l’utilisateur. Il est possible d’en ajouter un supplémentaire ensuite. Dossier à sauvegarder ? [${default_dir}] : "
read input_dir
if [[ "${input_dir}" == "" ]]; then
    dir1="${default_dir}"
    else dir1="${input_dir}"
fi

#### DOSSIER À SAUVEGARDER INTROUVABLE, ANNULATION ####
if [ ! -d "${dir1}" ]; then
    printf "\n"
    printf '\e[1;31m%-6s\e[m' "Dossier ${dir1} introuvable, installation annulée."
    printf "\n"
    exit
fi

#### DOSSIER SUPPLÉMENTAIRE ####
printf "Si vous avez un dossier supplémentaire à sauvegarder (/mnt/data par exemple) entrer-le maintenant, sinon laissez vide. [] : "
read input_dir2
if [[ "${input_dir2}" != "" ]]; then
    #### DOSSIER SUPPLÉMENTAIRE INTROUVABLE, ANNULATION DE CELUI-CI ####
    if [ ! -d "${input_dir2}" ]; then
        printf "\n"
        printf '\e[1;35m%-6s\e[m' "Dossier supplémentaire introuvable, non ajouté."
        printf "\n"
        else directories="'${dir1}','${input_dir2}'"
    fi
    else directories="'${dir1}'"
fi

#### INSTALLATION DE OPENSSH-SERVER ####
ensureSshdIsRunning
hostkey=$(getMyHostKey)
#printf "hostkey=$hostkey"
if [ "$?" != "$SUCCESS" ]; then
    printf '\e[1;31m%-6s\e[m' "Clé inaccessible, merci de contacter votre administrateur réseau, installation annulée."; exit
fi

#### CRÉATION DU FICHIER DE CONFIGURATION ####
fqdn="$(MyFqdn)"
filepl="${fqdn}.pl"
exclude="['ownCloud','.local/share/Trash','.cache','.Play*','.steam','.wine','Perso','temp','tmp','.Trash*','.DS_Store','._*']"
echo "\$Conf{XferMethod} = 'rsync';" > "${filepl}"
echo "\$Conf{RsyncShareName} = [${directories}];" >> "${filepl}"
echo "\$Conf{BackupFilesExclude} = {'*' => ${exclude} };" >> "${filepl}"
printf "\n"
printf '\e[1;34m%-6s\e[m' "Fichier de configuration serveur créé (${filepl})"
printf "\n"

#### ADRESSE MAIL DE L’UTILISATEUR ####
printf "Votre adresse e-mail ?\n : "
read input_mail

#### LE SERVEUR DOIT CONNAITRE ssh_host_ecdsa_key.pub DU CLIENT, L’ADRESSE MAIL ET L'IP ####
# mis en dernière ligne du fichier pl en attendant de trouver une meilleure solution
echo "# host:${fqdn}" >> "${filepl}"

cmd_hostkey=$(cat "${hostkey}")
echo "# hostkey:${cmd_hostkey}" >> "${filepl}"
echo "# mail:${input_mail}" >> "${filepl}"
echo "# ip:$(IpAddress)" >> "${filepl}"

#### AJOUTER LES DROITS EN LECTURE POUR LE GROUPE ####
# printf '\e[1;34m%-6s\e[m' "Ajout des droits en lecture pour le groupe sur les dossiers à sauvegarder (patience !)…"
# printf "\n"
# for dir in "${dir1}" "${input_dir2}"; do
#   find "${dir}" \( ! -regex '.*/\..*' \) -type f -exec chmod g+r {} \;
#   find "${dir}" \( ! -regex '.*/\..*' \) -type d -exec chmod g+rx {} \;
# done

#### CRÉATION DE L’UTILISATEUR BACKUPPC ####
printf '\e[1;34m%-6s\e[m' "Création du compte backuppc…"
printf "\n"
homebackuppc='/var/lib/backuppc'
AddUserBackuppc "${input_login}" "${homebackuppc}"
mkdir -p -- "${homebackuppc}/.ssh"
echo "from=\"129.20.203.16\" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDIhMc8ixQXfWDACJy4q0v8T877UxahhCjO51PQFzylwVpf88LX3yWeDrWIW0NRu0zoSm396mig918OpD5ggqML/QbYbQsoDdAFUV/tK4JU6UJgEQIl25MOcUBCFepsFBGS09CH/V07xSUqSP/+beeTRLNO2CQzk3S2y3YfkXpM7KmOGfeLgoCaQAcxIkgLXeM3TpCZEzJDlZ8c8k/DjVvsgwCpQktYzNo2b37KHLLfgyW9KSo6N9sReUuNQjS6lu8rjrXfc6+J0pY2D6IxWptTWL/JVrhFCUqe4QQy+xYjoR41wqnAQyl/kOcyBNhSvojMKwQT6vlPwru6pOno16/X backuppc@backuppc.ipr.univ-rennes1.fr" > $homebackuppc/.ssh/authorized_keys
chown -R backuppc "$homebackuppc/.ssh/"

printf "\n"
printf '\e[1;34m%-6s\e[m' "Configuration du poste terminée."
printf '\e[1;34m%-6s\e[m' "Envoyez bien votre fichier de configuration ($filepl) à Jéremy GARDAIS ou Anthony CARRÉ."
printf '\e[1;34m%-6s\e[m' "Vous pourrez affiner la configuration de votre sauvegarde depuis https://backuppc.ipr.univ-rennes1.fr"
printf "\n"
