#!/bin/bash
#
# sccl_add_node
#
# Zertifikat und Key fuer einen SCCL-Cluster-Knoten anlegen
###########################################################
#
cd $(dirname $0)
#
if [[ $PWD != */bin ]]; then
  cd bin
fi
#
BASEDIR=/etc/sccl
SCCLBINDIR=bin
#
MYPRG="sccl ${0##*/sccl_}"
#
NEWVERS='2'
#
unset CAPWD FORCE LOCAL MERGE OLDNODE merge force secondary unsecure checkonly
adminpwddat='adminpwd.dat'
while getopts clp:P:su-:? op; do
  case "$op" in
   c) checkonly=1;;
   l) LOCAL=1;;
   p) CAPWD="$OPTARG";;
   P) CAPWD="$(<$OPTARG)";;
   s) secondary=1
      unset adminpwddat;;
   u) secondary=1
      unsecure=1
      unset adminpwddat;;
   -) case "$OPTARG" in
       merge) MERGE=1
              merge='--merge';;
       force) FORCE=1
              force='--force';;
       oldversion) unset NEWVERS;;
       old)   OLDNODE=1;;
        *) echo "usage: $MYPRG [--oldversion] [--force] [--merge] [-c] [-l] [-s] [-u] [-p <CA-Key-PWD>|-P <CA-Key-PWD-File>] <Node Name>"
           exit 1;;
      esac;;
   *) echo "usage: $MYPRG [--oldversion] [--force] [--merge] [-c] [-l] [-s] [-u] [-p <CA-Key-PWD>|-P <CA-Key-PWD-File>] <Node Name>"
      exit 1;;
  esac
done
#
shift $(( $OPTIND - 1))
#
if [[ -z "$1" ]]; then
  echo "usage: $MYPRG <node-name>"
  exit 1
fi
#
if [[ -z "$LOCAL" ]] && ! ./sccl_check_config &>/dev/null; then
  echo "Die Clusterkonfiguration der Knoten ist nicht gleich:
"
  ./sccl_check_config -i $1
  exit 1
fi
#
if [[ -n "$MERGE" && -n "$LOCAL" ]]; then
  echo "Error: --merge und -l können nicht beide gesetzt sein."
  exit 1
fi
#
. $BASEDIR/sccl.conf
#
if [[ -z "$CLUSTER" ]]; then
  echo "Clustername nicht konfiguriert"
  exit 1
fi
#
NODENAME="$(tr '[:upper:]' '[:lower:]' <<<$1)"
#
if [[ `id -u` != 0 ]]
 then
  . globals.functions
  calllocal "sccl_add_node.s3w?force=$force&merge=$merge&nodename=$NODENAME"
  exit
fi
#
if [[ ! -w $BASEDIR/sccl.conf ]]; then
  echo "$BASEDIR/sccl.conf nicht gefunden oder kein Schreibrecht"
  exit 1
fi
#
if [[ ! -f /etc/sccl/certs/private/${CLUSTER}-cakey.pem ]]; then
  echo "CA-Key nicht gefunden. Neue Knoten können nur auf dem Masterknoten"
  echo "oder Knoten, auf die per 'sccl_dist_config -m' die Masterdaten kopiert wurden,"
  echo "generiert werden."
  exit 1
fi
#
if [[ -z "$CAPWD" && -f $BASEDIR/capwd.dat ]]; then
  CAPWD="$(<$BASEDIR/capwd.dat)"
fi
#
if [[ -z "$LOCAL" ]]; then
  if grep -q "^NODES=.*[\"[:blank:]]$NODENAME[\"[:blank:]]" $BASEDIR/sccl.conf; then
    echo "Error: Der Knoten $NODENAME ist schon im Cluster enthalten."
    exit 1
  fi
  #
  if [[ -n "$OLDNODE" ]]; then
    if [[ -n "$MERGE" ]]; then
      echo "error: --old und --merge ist nicht erlaubt."
      exit 1
    fi
  else
    TESTJOIN=$(httpget -s -u 'join' -p 'tocluster' -Sf -Sa $SCCLBASEDIR/data/JOINCLUSTER${NEWVERS}-ca.pem -Sk $SCCLBASEDIR/data/JOINCLUSTER${NEWVERS}-server-key.pem -Sc $SCCLBASEDIR/data/JOINCLUSTER${NEWVERS}-server-cert.pem ${NODENAME}:${U2WPORT} "test_join.s2w?joinnode=$NODENAME&merge=$MERGE")
    if [[ "$TESTJOIN" != "OK" ]]; then
      if [[ -n "$TESTJOIN" ]]; then
        echo "$TESTJOIN"
      else
        echo "Error: can't connect to $NODENAME"
        echo "       start 'sccl join_cluster' on $NODENAME"
        echo "To add pre 2.9 node:"
        echo "       $0 --oldversion $*"
      fi
      exit 1
    fi
  fi
fi
#
[[ -n "$checkonly" ]] && exit 0
#
if [[ -n "$MERGE" ]]; then
  MYPACKAGESGREP=$(./sccl_list_packages -f | awk '{if(NR>1)printf("|");printf("^%s$", $1)}')
  if [[ -n "$MYPACKAGESGREP" ]]; then
    DOUBLEPACKAGES=$(httpget -s -u 'join' -p 'tocluster' -Sf -Sa $SCCLBASEDIR/data/JOINCLUSTER${NEWVERS}-ca.pem -Sk $SCCLBASEDIR/data/JOINCLUSTER${NEWVERS}-server-key.pem -Sc $SCCLBASEDIR/data/JOINCLUSTER${NEWVERS}-server-cert.pem ${NODENAME}:${U2WPORT} "sccl_list_packages.s2w?flags=-j" | grep -E "$MYPACKAGESGREP" | sort -u | awk '{if(NR>1)printf(", ");printf("%s", $1)}')
    if [[ -n "$DOUBLEPACKAGES" ]]; then
      echo "Error: Duplicate packages: $DOUBLEPACKAGES."
      exit 1
    fi
  fi
  MYRESOURCESGREP=$(./sccl_list_resources | awk '{if(NR>1)printf("|");printf("^%s$", $1)}')
  if [[ -n "$MYRESOURCESGREP" ]]; then
    DOUBLERESOURCES=$(httpget -s -u 'join' -p 'tocluster' -Sf -Sa $SCCLBASEDIR/data/JOINCLUSTER${NEWVERS}-ca.pem -Sk $SCCLBASEDIR/data/JOINCLUSTER${NEWVERS}-server-key.pem -Sc $SCCLBASEDIR/data/JOINCLUSTER${NEWVERS}-server-cert.pem ${NODENAME}:${U2WPORT} "sccl_list_resources.s2w?flags=-j" | grep -E "$MYRESOURCESGREP" | sort -u | awk '{if(NR>1)printf(", ");printf("%s", $1)}')
    if [[ -n "$DOUBLERESOURCES" ]]; then
      echo "Error: Duplicate resources: $DOUBLERESOURCES."
      exit 1
    fi
  fi
fi
#
. $BASEDIR/certs.conf
#
if [[ ! -d $BASEDIR/certs/private ]]; then
  mkdir -m 700 $BASEDIR/certs/private
fi
#
if [[ -f $BASEDIR/certs/private/${CLUSTER}-${NODENAME%%.*}-key.pem || -f certs/${CLUSTER}-${NODENAME%%.*}-cert.pem ]]; then
  echo "Der Key fuer $NODENAME ist schon angelegt."
  if [[ -z "$FORCE" ]]; then
    echo "$MYPRG --force <Client> legt den Key neu an."
    exit 1
  fi
fi
#
echo "SCCL-Node-Zertifikat erstellen"
echo
openssl req -new -newkey rsa:2048 -batch -subj "/C=$DE/ST=$STATE/L=$CITY/O=$COMPANY/OU=$OU/CN=$NODENAME/emailAddress=$EMAIL" -out $BASEDIR/certs/certs/${CLUSTER}-${NODENAME%%.*}-csr.pem -nodes -keyout $BASEDIR/certs/private/${CLUSTER}-${NODENAME%%.*}-key.pem
chmod 400 $BASEDIR/certs/private/${CLUSTER}-${NODENAME%%.*}-key.pem
#
if [[ -n "$CAPWD" ]]; then
  openssl x509 -req -passin "pass:$CAPWD" -in $BASEDIR/certs/certs/${CLUSTER}-${NODENAME%%.*}-csr.pem -out $BASEDIR/certs/certs/${CLUSTER}-${NODENAME%%.*}-cert.pem -CA $BASEDIR/certs/${CLUSTER}-ca.pem -CAkey $BASEDIR/certs/private/${CLUSTER}-cakey.pem -CAserial $BASEDIR/certs/serial -days 3650
else
  openssl x509 -req -in $BASEDIR/certs/certs/${CLUSTER}-${NODENAME%%.*}-csr.pem -out $BASEDIR/certs/certs/${CLUSTER}-${NODENAME%%.*}-cert.pem -CA $BASEDIR/certs/${CLUSTER}-ca.pem -CAkey $BASEDIR/certs/private/${CLUSTER}-cakey.pem -CAserial $BASEDIR/certs/serial -days 3650
fi
chmod 444 $BASEDIR/certs/certs/${CLUSTER}-${NODENAME%%.*}-cert.pem
rm $BASEDIR/certs/certs/${CLUSTER}-${NODENAME%%.*}-csr.pem
#
if [[ -z "$LOCAL" ]]; then
  if ! grep -q "^NODES=.*[\"[:blank:]]$NODENAME[\"[:blank:]]" $BASEDIR/sccl.conf; then
    sed -i "s/^NODES=\"\\([^\"]*\\)\"/NODES=\"\\1 $NODENAME\"/" $BASEDIR/sccl.conf
  fi
  if [[ -n "$secondary" ]]; then
    sed -i "/^SECONDARYNODES=\"/{s/=\"\\([^\"]*\\)\"/=\"\\1 $NODENAME\"/;s/=\" /=\"/}" $BASEDIR/sccl.conf
  fi
  if [[ -n "$unsecure" ]]; then
    sed -i "/^UNSECURENODES=\"/{s/=\"\\([^\"]*\\)\"/=\"\\1 $NODENAME\"/;s/=\" /=\"/}" $BASEDIR/sccl.conf
  fi
  #
  ./sccl_update_ips -l
  #
  if [[ -n "$MERGE" ]]; then
    echo "
#######################################
# Packages from new node ${NODENAME}
#######################################
" >>$PACKAGES
    httpget -s -u 'join' -p 'tocluster' -Sf -Sa $SCCLBASEDIR/data/JOINCLUSTER${NEWVERS}-ca.pem -Sk $SCCLBASEDIR/data/JOINCLUSTER${NEWVERS}-server-key.pem -Sc $SCCLBASEDIR/data/JOINCLUSTER${NEWVERS}-server-cert.pem ${NODENAME}:${U2WPORT} "sccl_read_config.s3w?config=PACKAGES&flags=-j" | grep -E -B 2 -A 1 '^[^#]' | sed -s 's/^--$//' >>$PACKAGES
    #
    echo "
#######################################
# Resources from new node ${NODENAME}
#######################################
" >>$RESOURCES
    httpget -s -u 'join' -p 'tocluster' -Sf -Sa $SCCLBASEDIR/data/JOINCLUSTER${NEWVERS}-ca.pem -Sk $SCCLBASEDIR/data/JOINCLUSTER${NEWVERS}-server-key.pem -Sc $SCCLBASEDIR/data/JOINCLUSTER${NEWVERS}-server-cert.pem ${NODENAME}:${U2WPORT} "sccl_read_config.s3w?config=RESOURCES&flags=-j" | grep -E -B 2 -A 1 '^[^#]' | sed -s 's/^--$//' >>$RESOURCES
    #
  fi
  ./sccl_dist_config $BASEDIR/sccl.conf $PACKAGES $RESOURCES $U2WHOSTSDAT
  #
  if [[ -d $BASEDIR/scripts ]]; then
    SCRIPTS=scripts
  else
    SCRIPTS=''
  fi
  tar cvfz /tmp/${CLUSTER}-${NODENAME}.tgz -C $BASEDIR sccl.conf localadminpwd.dat $adminpwddat userpwd.dat ${PACKAGES##*/} ${RESOURCES##*/} ${U2WPWDDAT##*/} ${U2WHOSTSDAT##*/} $SCRIPTS certs/${CLUSTER}-ca.pem certs/private/${CLUSTER}-${NODENAME%%.*}-key.pem certs/certs/${CLUSTER}-${NODENAME%%.*}-cert.pem 2>/dev/null
  #
  MYTIMESTAMP=`date '+%s'`
  if RET=`httpget -s -u 'join' -p 'tocluster' -Sf -Sa $SCCLBASEDIR/data/JOINCLUSTER${NEWVERS}-ca.pem -Sk $SCCLBASEDIR/data/JOINCLUSTER${NEWVERS}-server-key.pem -Sc $SCCLBASEDIR/data/JOINCLUSTER${NEWVERS}-server-cert.pem -mf /tmp/${CLUSTER}-${NODENAME}.tgz -mn SCCLDATA ${NODENAME}:${U2WPORT} "join_to_cluster.s2w?joinnode=$NODENAME&timestamp=$MYTIMESTAMP"`; then
    if [[ `echo "$RET" | tail -1` = 'JOINED' ]]; then
      rm /tmp/${CLUSTER}-${NODENAME}.tgz
      echo "Der Knoten ist hinzugefuegt."
      echo "$RET" | grep -F 'WARNING'
      exit 0
    else
      echo "Der Join hat nicht geklappt: $RET"
    fi
  fi
  echo "Der Join kann manuell erfolgen, indem die Datei /tmp/${CLUSTER}-${NODENAME}.tgz"
  echo "Auf dem neuen Knoten unter $BASEDIR entpackt wird."
else
  ./sccl_update_ips -l
fi
