#!/bin/bash

print_help() {
    cat <<HELP
USAGE: proxy-ssh-push-init [options]

options:
  -k path to existing key
  -s only configure sshd and exit
  -a only authorize parent key and exit
  -h show this help message and exit
HELP
    exit 1
}

SYSCONFIG_DIR=/etc/sysconfig/rhn
UP2DATE_FILE=$SYSCONFIG_DIR/up2date
RHN_PARENT=$(awk -F= '/serverURL=/ {split($2, a, "/")} END { print a[3]}' $UP2DATE_FILE)
PROTO=$(awk -F= '/serverURL=/ {split($2, a, "/"); split(a[1], b, ":")} END { print b[1]}' $UP2DATE_FILE)
HTMLPUB_DIR=/srv/www/htdocs/pub

SSH_PUSH_KEY_FILE="id_susemanager_ssh_push"
SSH_PUSH_USER="mgrsshtunnel"
SSH_PUSH_USER_HOME="/var/lib/spacewalk/$SSH_PUSH_USER"
SSH_PUSH_KEY_DIR="$SSH_PUSH_USER_HOME/.ssh"

generate_or_import_ssh_push_key() {
    # create user if needed
    getent group $SSH_PUSH_USER >/dev/null || groupadd -r $SSH_PUSH_USER
    getent passwd $SSH_PUSH_USER >/dev/null || useradd -r -g $SSH_PUSH_USER -m -d $SSH_PUSH_USER_HOME -c "susemanager ssh push tunnel" $SSH_PUSH_USER

    # create .ssh dir in home and set permissions
    mkdir -p $SSH_PUSH_KEY_DIR
    chown $SSH_PUSH_USER:$SSH_PUSH_USER $SSH_PUSH_KEY_DIR
    chmod 700 $SSH_PUSH_KEY_DIR

    # backup first any existing keys
    if [ -f $SSH_PUSH_KEY_DIR/${SSH_PUSH_KEY_FILE} ]; then
       local TSTMP=$(date +%Y%m%d%H%M)
       mv $SSH_PUSH_KEY_DIR/$SSH_PUSH_KEY_FILE $SSH_PUSH_KEY_DIR/${SSH_PUSH_KEY_FILE}.${TSTMP}
       mv $SSH_PUSH_KEY_DIR/${SSH_PUSH_KEY_FILE}.pub $SSH_PUSH_KEY_DIR/${SSH_PUSH_KEY_FILE}.pub.${TSTMP}
    fi

    # import existing or generate new ssh key for this proxy
    if [ "$USE_EXISTING_SSH_PUSH_KEY" -eq "1" ]; then
        if [[ -z "$EXISTING_SSH_KEY" || ( ! -r "$EXISTING_SSH_KEY" || ! -r "${EXISTING_SSH_KEY}.pub" ) ]]; then
            echo "Key $EXISTING_SSH_KEY not found."
            exit 1
        fi
        echo "Copying SSH keys to ${SSH_PUSH_KEY_DIR}."
        cp $EXISTING_SSH_KEY $SSH_PUSH_KEY_DIR/$SSH_PUSH_KEY_FILE
        cp ${EXISTING_SSH_KEY}.pub $SSH_PUSH_KEY_DIR/${SSH_PUSH_KEY_FILE}.pub
    else
        echo "Generating new SSH key for ssh-push minions."
        ssh-keygen -q -N '' -C "susemanager-ssh-push" -f $SSH_PUSH_KEY_DIR/$SSH_PUSH_KEY_FILE
    fi
    # change owner to SSH_PUSH_USER
    chown $SSH_PUSH_USER:$SSH_PUSH_USER $SSH_PUSH_KEY_DIR/$SSH_PUSH_KEY_FILE
    chmod 600 $SSH_PUSH_KEY_DIR/$SSH_PUSH_KEY_FILE
    chown $SSH_PUSH_USER:$SSH_PUSH_USER $SSH_PUSH_KEY_DIR/$SSH_PUSH_KEY_FILE.pub
    chmod 644 $SSH_PUSH_KEY_DIR/$SSH_PUSH_KEY_FILE.pub

    # copy the public key to apache's pub dir
    cp $SSH_PUSH_KEY_DIR/${SSH_PUSH_KEY_FILE}.pub ${HTMLPUB_DIR}/
}

authorize_parent_ssh_push_key() {
    # Fetch key from parent and add it to authorized_keys
    local AUTH_KEYS="$SSH_PUSH_KEY_DIR/authorized_keys"
    local TMP_PUSH_KEY_FILE="$SSH_PUSH_KEY_DIR/${SSH_PUSH_KEY_FILE}.pub.tmp"
    rm -f $TMP_PUSH_KEY_FILE
    local PROXY_KEY_URL="$PROTO://$RHN_PARENT/pub/${SSH_PUSH_KEY_FILE}.pub"
    local SERVER_KEY_URL="$PROTO://$RHN_PARENT/rhn/manager/download/saltssh/pubkey"
    echo "Fetching public ssh-push key from $RHN_PARENT."
    local CURL_RESPONSE=$(curl --write-out %{http_code} --silent --output $TMP_PUSH_KEY_FILE $PROXY_KEY_URL)
    if [ "$CURL_RESPONSE" == "404" ]; then
        # parent is a Manager server
        CURL_RESPONSE=$(curl --write-out %{http_code} --silent --output $TMP_PUSH_KEY_FILE $SERVER_KEY_URL)
    fi
    if [ "$CURL_RESPONSE" != "200" ]; then
        echo "Could not retrieve ssh-push key. curl failed with HTTP response code ${CURL_RESPONSE}."
        echo "Check connectivity to the parent server or if it has a ssh-push key."
        echo "After fixing the problem run: mgr-proxy-ssh-push-init -a"
    else
        # remove any previously authorized key
        [ -f $AUTH_KEYS ] && sed -i '/susemanager-ssh-push/d' $AUTH_KEYS
        cat $TMP_PUSH_KEY_FILE >> $AUTH_KEYS && echo "Added public ssh-push key from $RHN_PARENT to $AUTH_KEYS."
    fi
    rm $TMP_PUSH_KEY_FILE
}

configure_sshd() {
    local SSHD_CONFIG="/etc/ssh/sshd_config"
    if ! grep "^[^#]*Match user $SSH_PUSH_USER" $SSHD_CONFIG> /dev/null ; then
        cat >> $SSHD_CONFIG <<EOF

Match user mgrsshtunnel
    ForceCommand /usr/sbin/mgr-proxy-ssh-force-cmd
    KbdInteractiveAuthentication no
    PasswordAuthentication no
    PubkeyAuthentication yes
    X11Forwarding no
    PermitTTY no

EOF
        echo "Updated ${SSHD_CONFIG}."
        printf "Restarting sshd..."
        systemctl restart sshd
        echo "done."
    else
        echo "sshd is already configured."
    fi
}

USE_EXISTING_SSH_PUSH_KEY=0
while getopts ":k:s:ah" opt; do
  case $opt in
    k)
      USE_EXISTING_SSH_PUSH_KEY=1
      EXISTING_SSH_KEY=$OPTARG
      ;;
    h)
      print_help
      exit 0
      ;;
    s)
      configure_sshd
      exit 0
      ;;
    a)
      authorize_parent_ssh_push_key
      exit 0
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      exit 1
      ;;
    :)
      echo "Option -$OPTARG requires an argument." >&2
      exit 1
      ;;
  esac
done

generate_or_import_ssh_push_key
authorize_parent_ssh_push_key
configure_sshd