#!/bin/ash
set -e

SETUP_DIR="/app/setup"
CONFIG_DIR="${SETUP_DIR}/config"

BURPUI_CONFIG=${BURPUI_CONFIG:-/etc/burp/burpui.cfg}
BURPUI_MONITOR_CONFIG=${BURPUI_MONITOR_CONFIG:-/etc/burp/bui-monitor.cfg}
BURPUI_CLIENT_NAME=${BURPUI_CLIENT_NAME:-bui}
BURPUI_VERBOSE=${BURPUI_VERBOSE:-0}
BURPUI_UID=${BURPUI_UID:-5337}
BURPUI_GID=${BURPUI_GID:-5337}
BURPUI_PLUGINS=${BURPUI_PLUGINS:-none}
BURPUI_WS_WORKERS=${BURPUI_WS_WORKERS:-$(getconf _NPROCESSORS_ONLN)}
BURPUI_RP_SCHEME=${BURPUI_RP_SCHEME:-https}
BURPUI_BACKEND=${BURPUI_BACKEND:-async}
BURP_CLIENT_CONFIG=${BURP_CLIENT_CONFIG:-/tmp/burp.conf}
BURP_SERVER_CONFIG=${BURP_SERVER_CONFIG:-/etc/burp/burp-server.conf}
BURP_SERVER_ADDR=${BURP_SERVER_ADDR:-burp-server}
REDIS_SERVER=${REDIS_SERVER:-redis:6379}
DATABASE_URL=${DATABASE_URL:-postgresql://burpui:burpui@pgsql/burpuidb}
GUNICORN_WORKERS=${GUNICORN_WORKERS:-$(getconf _NPROCESSORS_ONLN)}
GUNICORN_WORKER_CLASS=${GUNICORN_WORKER_CLASS:-sync}
ASYNC_POOL_SIZE=${ASYNC_POOL_SIZE:-$(getconf _NPROCESSORS_ONLN)}
TIMEZONE=${TIMEZONE:-Europe/Paris}

trap appStop SIGINT SIGTERM

doas() {
  user=$1
  shift
  su -l $user -c "$@"
}

appStart () {

  [ -e /usr/share/zoneinfo/$TIMEZONE ] && {
    cp /usr/share/zoneinfo/$TIMEZONE /etc/localtime
    echo "$TIMEZONE" >/etc/timezone
  }

  # Create burp-ui User
  getent group | grep -q burpui || addgroup -g $BURPUI_GID burpui
  getent passwd | grep -q burpui || adduser -h /var/lib/burpui -D -s /bin/ash -u $BURPUI_UID -G burpui burpui
  chown -R burpui: /var/log/gunicorn

  [ -e /etc/burp/this_is_a_decoy_file_to_know_if_we_can_chown ] && {
    chown -R burpui: /etc/burp
    rm /etc/burp/this_is_a_decoy_file_to_know_if_we_can_chown
  }

  [ "$BURP_SERVER_ADDR" == "auto" ] && {
    BURP_SERVER_ADDR=$(ip route sh | grep default | awk '{print $3;}')
  }

  [ -e "$BURPUI_CONFIG" ] || {
    cp /usr/local/share/burpui/etc/burpui.sample.cfg $BURPUI_CONFIG
    chown burpui: $BURPUI_CONFIG
  }

  [ -e "$BURPUI_MONITOR_CONFIG" ] || {
    cp /usr/local/share/burpui/etc/buimonitor.sample.cfg $BURPUI_MONITOR_CONFIG
    chown burpui: $BURPUI_MONITOR_CONFIG
  }

  # wait for redis to be up
  sleep 3

  LOGFILE=$(doas burpui mktemp)
  echo "Setting up burp & burp-ui:"
  COMMAND="bui-manage -c $BURPUI_CONFIG setup_burp --burp-conf-cli $BURP_CLIENT_CONFIG --burp-conf-serv $BURP_SERVER_CONFIG --host $BURP_SERVER_ADDR --client $BURPUI_CLIENT_NAME --redis $REDIS_SERVER --database $DATABASE_URL --plugins $BURPUI_PLUGINS --monitor $BURPUI_MONITOR_CONFIG --concurrency $ASYNC_POOL_SIZE --backend $BURPUI_BACKEND"
  echo $COMMAND
  doas burpui "$COMMAND 2>&1 | tee $LOGFILE"
  ret=$?

  ASYNC="True"
  CELERY="True"
  grep -q "Unable to contact the redis server" $LOGFILE && CELERY=""
  [ "$GUNICORN_WORKER_CLASS" != "sync" ] || [ "$BURPUI_BACKEND" != "async" ] && ASYNC=""

  [ "$ret" != "0" ] && {
    echo
    echo "Something went wrong while setting up burp & burp-ui!"
    echo "8<---------------------------------------------------"
    cat $LOGFILE
    echo "8<---------------------------------------------------"
  }
  rm $LOGFILE

  [ "$DATABASE_URL" != "none" ] && {
    doas burpui "/usr/local/bin/bui-manage -c $BURPUI_CONFIG db upgrade"
  }

  # Check websocket is available and not embedded
  WEBSOCKET="True"
  [ "$BURPUI_WS_WORKERS" == "0" ] && {
    WEBSOCKET=""
  } || {
    WS_EMBEDDED=$(doas burpui "/usr/local/bin/bui-manage -c $BURPUI_CONFIG sysinfo | grep 'WebSocket embedded' | tr -s ' ' | cut -d' ' -f3")
    WS_AVAILABLE=$(doas burpui "/usr/local/bin/bui-manage -c $BURPUI_CONFIG sysinfo | grep 'WebSocket available' | tr -s ' ' | cut -d' ' -f3")
    [ "$WS_EMBEDDED" == "True" ] && WEBSOCKET="" || {
      [ "$WS_AVAILABLE" != "True" ] && WEBSOCKET=""
    }
  }

  # Setup nginx workers
  cat ${CONFIG_DIR}/nginx/workers_header.conf >/etc/nginx/workers.conf

  [ "$WEBSOCKET" == "True" ] && {
    for i in $(seq $BURPUI_WS_WORKERS)
    do
      WORKER_ID=$i
      WORKER_PORT=$(( 5000 + $i ))
      sed -r "s'@BURPUI_CONFIG@'$BURPUI_CONFIG';s'@WORKER_ID@'$WORKER_ID';s'@WORKER_PORT@'$WORKER_PORT'" /etc/supervisor.d/websocket.ini.sample > /etc/supervisor.d/websocket-$WORKER_ID.ini
      echo "    server 127.0.0.1:$WORKER_PORT;" >>/etc/nginx/workers.conf
    done
    echo "}" >>/etc/nginx/workers.conf
  } || {
    cat >>/etc/nginx/workers.conf<<EOF
    server 127.0.0.1:5000;
}
EOF
  }

  # You can change log verbosity at runtime
  sed -r "s'@BURPUI_CONFIG@'$BURPUI_CONFIG';s'@BURPUI_VERBOSE@'$BURPUI_VERBOSE'" /etc/supervisor.d/gunicorn.ini.sample >/etc/supervisor.d/gunicorn.ini

  sed -r "s'@BURPUI_CONFIG@'$BURPUI_CONFIG'" /etc/supervisor.d/bui-celery.ini.sample >/etc/supervisor.d/bui-celery.ini
  sed -r "s'@BURPUI_MONITOR_CONFIG@'$BURPUI_MONITOR_CONFIG'" /etc/supervisor.d/bui-monitor.ini.sample >/etc/supervisor.d/bui-monitor.ini

  sed -r "s'@GUNICORN_WORKERS@'$GUNICORN_WORKERS';s'@GUNICORN_WORKER_CLASS@'$GUNICORN_WORKER_CLASS'" /etc/burp-ui/burpui_gunicorn.py.sample >/etc/burp-ui/burpui_gunicorn.py

  sed -r "s'@HTTP_SCHEME@'$BURPUI_RP_SCHEME'" ${CONFIG_DIR}/nginx/nginx.conf >/etc/nginx/nginx.conf

  ssl_cert_ca=$(grep -E "^\s*ssl_cert_ca\s*=" $BURP_CLIENT_CONFIG | cut -d= -f2 | sed -e "s/\s*//g")
  ssl_cert=$(grep -E "^\s*ssl_cert\s*=" $BURP_CLIENT_CONFIG | cut -d= -f2 | sed -e "s/\s*//g")
  ssl_key=$(grep -E "^\s*ssl_key\s*=" $BURP_CLIENT_CONFIG | cut -d= -f2 | sed -e "s/\s*//g")

  [ -z "$ssl_cert_ca" ] && {
    echo "Unable to locate ssl_cert_ca in $BURP_CLIENT_CONFIG"
    exit 1
  }
  [ -z "$ssl_cert" ] && {
    echo "Unable to locate ssl_cert in $BURP_CLIENT_CONFIG"
    exit 1
  }
  [ -z "$ssl_key" ] && {
    echo "Unable to locate ssl_key in $BURP_CLIENT_CONFIG"
    exit 1
  }

  # start supervisord
  /usr/bin/supervisord -c /etc/supervisord.conf

  echo "Starting crond..."
  supervisorctl start cron >/dev/null

  [ -n "$CELERY" ] && {
    echo "Starting bui-celery..."
    supervisorctl start bui-celery >/dev/null
  }

  [ -n "$ASYNC" ] && {
    echo "Starting bui-monitor..."
    supervisorctl start bui-monitor >/dev/null
  }

  echo "Starting gunicorn..."
  supervisorctl start gunicorn >/dev/null

  [ "$WEBSOCKET" == "True" ] && {
    for i in $(seq $BURPUI_WS_WORKERS)
    do
      echo "Starting websocket worker $i..."
      supervisorctl start websocket-$i
    done
  }

  echo "Starting nginx..."
  supervisorctl start nginx >/dev/null

  # wait a bit for the logs to be populated
  sleep 2

  # watch the access logs
  tail -F /var/log/gunicorn/burp-ui_info.log
}

appStop() {
  echo ""
  echo "Stopping nginx..."
  supervisorctl stop nginx >/dev/null

  echo "Stopping bui-celery..."
  supervisorctl stop bui-celery &>/dev/null || true

  echo "Stopping bui-monitor..."
  supervisorctl stop bui-monitor &>/dev/null || true

  for i in $(seq $BURPUI_WS_WORKERS)
  do
    echo "Stopping websocket worker $i..."
    supervisorctl stop websocket-$i &>/dev/null || true
  done

  echo "Stopping gunicorn..."
  supervisorctl stop gunicorn >/dev/null
  echo "Stopping crond..."
  supervisorctl stop cron >/dev/null
  echo "Stopping supervisord..."
  kill -15 $(cat /var/run/supervisord.pid)
  exit
}

appHelp () {
  echo "Available options:"
  echo " app:start          - Starts the burp-ui server (default)"
  echo " app:help           - Displays the help"
  echo " [command]          - Execute the specified linux command eg. bash."
}

case "$1" in
  app:start)
    appStart
    ;;
  *)
    if [ -x $1 ]; then
      $1
    else
      prog=$(which $1)
      if [ -n "${prog}" ] ; then
        shift 1
        su -l burpui -c "$prog $@"
      else
        appHelp
      fi
    fi
    ;;
esac

exit 0
