#!/bin/bash 

###########################################################################################################
# Header
#
AXIOM_PATH="$HOME/.axiom"
source "$AXIOM_PATH/interact/includes/vars.sh"
source "$AXIOM_PATH/interact/includes/system-notification.sh"

############################################################################################################
# Variable Declarations
#
region="$(jq -r '.region' "$AXIOM_PATH"/axiom.json)"
builder="$(jq -r '.provider' "$AXIOM_PATH"/axiom.json)"
provisioner="$1"
start_time=$(date +%s)
op_ssh_password=$(cat /dev/urandom| base64 | head -c 128 | tr -d '+=-' | tr -d '\n' | tr -d /)
account_path=$(ls -la $AXIOM_PATH/axiom.json | rev | cut -d " " -f 1 | rev)
provider="$(cat "$AXIOM_PATH/axiom.json" | jq -r '.provider')"
BASEOS="$(uname)"

############################################################################################################
# Get the provisioner file
#
if [ -z "$provisioner" ]; then
    echo -e ""
    echo -e '\033[1mTime to pick your provisioner. Options: default, reconftw, barebones, custom\033[0m'
    echo -e "${Yellow}Default: is our latest iteration of axiom provisioners. It comes with all tools installed and has been optimized for readability. Recommended for axiom-fleet${Color_Off}"
    echo -e "${Green}ReconFTW: includes all tools in ReconFTW and works with most modules. Recommended for ReconFTW.${Color_Off}"
    echo -e "${Yellow}Barebones: a decently secure base install, comes with Docker, Go-lang, Interlace and nmap installed. Recommended for templating.${Color_Off}"
    echo -e "${Green}Custom: custom Packer JSON you provide.${Color_Off}"
    echo -e -n "${Blue}Which axiom provisioner would you like to use: default, reconftw, barebones, custom? (option: press enter to select Default) \n>>${Color_Off}"

    read ans
    if [[ $ans == "default" ]] || [[ $ans == "Default" ]]; then 
              echo -e "${Green}Selected provisioner option 'Default'${Color_Off}"
              provisioner="default"
    fi
    if [[ $ans == "reconftw" ]] ||  [[ $ans == "Reconftw" ]] ||  [[ $ans == "ReconFTW" ]]; then
               echo -e "${Green}Selected provisioner option 'ReconFTW'${Color_Off}"
               provisioner="reconftw"
    fi
    if [[ $ans == "barebones" ]] || [[ $ans == "Barebones" ]]; then
               echo -e "${Green}Selected provisioner option 'Barebones'${Color_Off}"
               provisioner="barebones"
    fi
    if [[ $ans == "custom" ]] || [[ $ans == "Custom" ]]; then
               echo -e "${Red}Your Packer JSON must be located in "$AXIOM_PATH/images/provisioners/". Make sure to move it.${Color_Off}"
               echo -e "${Green}Listing all provisioners available in "$AXIOM_PATH/images/provisioners/" ...${Color_Off}"
               ls -1 $AXIOM_PATH/images/provisioners/ | sort -u | sed -e 's/\.json$//' | grep -v -w 'ibm-base-image-create.sh' 
               echo -e -n "${Green}Enter the provisioner filename. \n>>${Color_Off}"
               read ans
               provisioner=$ans
               echo -e "${Green}Selected provisioner option 'Custom', using $ans ${Color_Off}"
    fi
    if [[ $ans == "" ]]; then
	       echo -e "${Green}Selected default provisioner option 'Default'${Color_Off}"
               provisioner="default"
    fi
fi

############################################################################################################
# opportunity to cancel axiom-build
#
echo -e "${Red}Now your account is setup, now running axiom-build"
echo "A build will take about 25 minutes, spin up a temporary instance, and then snapshot it to use for our future boxes"
echo -e "Starting Build in 5 seconds... Ctrl+C to quit, remember, you can just type axiom-build at any time${Color_Off}"
sleep 5

############################################################################################################
# check the provisioner and bulder exist 
#
if [ ! -z $1 ]
then
	provisioner="$1"
fi
prov_path="$AXIOM_PATH/images/provisioners/$provisioner.json"
builder_path="$AXIOM_PATH/images/builders/$builder.json"
if [ ! -f "$prov_path" ]
then
	echo -e "${Red}Error: unfortunately, can not find provisioner path...${Color_Off}"
	exit
fi
if [ ! -f "$builder_path" ]
then
	echo -e "${Red}Error: unfortunately, can not find builder path...${Color_Off}"
	exit
fi

############################################################################################################
# Generate the Packer final provisioner by combining the Cloud Provider builder and provisioner file
#
snapshot_name=axiom-$provisioner-$(date +%s)
image_path="$AXIOM_PATH/images/axiom.json"
$AXIOM_PATH/interact/axiom-provider "$provider"
"$AXIOM_PATH"/interact/generate_packer "$builder" "$provisioner"

#############################################################################################################
# Add SSH Key in account.json to $AXIOM_PATH/configs/authorized_keys
# If SSH key in account.json doesnt exists, create axiom_rsa SSH key and add that to $AXIOM_PATH/configs/authorized_keys
# TIPS: if you want to swap out the SSH key axiom uses, just edit the account.json.
# For example: change key:value pair "sshkey": "id_rsa" to "sshkey": "axiom_rsa" and rerun axiom-build.
#
account_path=$(ls -la $AXIOM_PATH/axiom.json | rev | cut -d " " -f 1 | rev)
sshkey="$(cat "$AXIOM_PATH/axiom.json" | jq -r '.sshkey')"

# If custom SSH key is found in "$AXIOM_PATH/axiom.json", add it to Packer builder
if [ -f ~/.ssh/$sshkey ] ; then
 echo -e "${Blue}Adding $sshkey SSH key to Packer Builder${Color_Off}"
 cat ~/.ssh/$sshkey.pub >$AXIOM_PATH/configs/authorized_keys

# If axiom_rsa key is already created but not in "$AXIOM_PATH/axiom.json", add it to $AXIOM_PATH/axiom.json" and Packer builder
elif [ -f ~/.ssh/axiom_rsa ] ; then
 echo -e "${Blue}Adding axiom_rsa SSH key to Packer Builder${Color_Off}"
 cat ~/.ssh/axiom_rsa.pub >$AXIOM_PATH/configs/authorized_keys
 jq '.sshkey="'axiom_rsa'"' <"$account_path">"$AXIOM_PATH"/tmp.json ; mv "$AXIOM_PATH"/tmp.json "$account_path"

# If axiom_rsa is not created, create it and then add it to "$AXIOM_PATH/axiom.json" and Packer builder
else 
 echo -e "${Blue}Creating axiom SSH key in ~/.ssh/axiom_rsa.pub and adding it to Packer Builder${Color_Off}"
 ssh-keygen -b 2048 -t rsa -f ~/.ssh/axiom_rsa -q -N ""
 jq '.sshkey="'axiom_rsa'"' <"$account_path">"$AXIOM_PATH"/tmp.json ; mv "$AXIOM_PATH"/tmp.json "$account_path"
 cat ~/.ssh/axiom_rsa.pub >$AXIOM_PATH/configs/authorized_keys
fi

if [[ ! -f "$AXIOM_PATH/configs/authorized_keys" ]]
then
	echo -e "${BRed}You have no authorized keys file at $AXIOM_PATH/configs/authorized_keys"
	echo -e  "Please make sure an SSH key exists in ~/.axiom/axiom.json or rerun axiom-configure."
	echo -e "Then run axiom-build..${Color_Off}"
	exit
fi

#############################################################################################################
# If axiom_path isnt set, exit
#
cd "$AXIOM_PATH"/ || exit

#############################################################################################################
# change password or fail
#
if [ -z "$op_ssh_password" ]; then 
    echo -e "Unable to generate random password for Packer image.. exiting"
    exit 0
fi

#############################################################################################################
# Display account.json one last time, since its been updated
#
echo -e "${Green}Password for user op is stored in $account_path, for your records${Color_Off}"
cat "$account_path" | jq '.do_key = "************************************************************************"'

#############################################################################################################
# Change packer version for IBM
#
if [[ "$provider" == "ibm" ]]; then
mkdir -p /tmp/packer-ibm/
 if [[ ! -f /tmp/packer-ibm/packer ]]; then
  if [[ $BASEOS == "Linux" ]]; then
   wget -q -O /tmp/packer.zip https://releases.hashicorp.com/packer/1.5.6/packer_1.5.6_linux_amd64.zip && cd /tmp/ && unzip packer.zip && mv packer /tmp/packer-ibm/ && rm /tmp/packer.zip
  elif [[ $BASEOS == "Darwin" ]]; then
   wget -q -O /tmp/packer.zip https://releases.hashicorp.com/packer/1.5.6/packer_1.5.6_darwin_amd64.zip && cd /tmp/ && unzip packer.zip && mv packer /tmp/packer-ibm/ && rm /tmp/packer.zip 
  fi
 fi

BASEOS="$(uname)"
case $BASEOS in
'Darwin')
    PATH="/tmp/packer-ibm/:$(brew --prefix coreutils)/libexec/gnubin:$PATH"
    ;;
'Linux')
    PATH="/tmp/packer-ibm:$PATH"
    ;;
*) ;;
esac
fi

# ###########################################################################################################
# Execute the Packer binary to build the final image
#
counter=0
echo -e "${BWhite}Building image $provisioner for provider $builder... This can take up to 25 minutes so please be patient!\nIf this fails, verify the account is properly configured and/or try a different region.${Color_Off}"

if [[ $provisioner == "azure" ]]; then
    cp $AXIOM_PATH/axiom.json $AXIOM_PATH/axiom_bck.json
    sed -i "/\"region\"/d" > $AXIOM_PATH/axiom.json
fi

if packer build -var-file "$AXIOM_PATH"/axiom.json -var "variant=$provisioner" -var "op_random_password=$op_ssh_password" -var "snapshot_name=$snapshot_name" "$image_path";
then
	end_time=$(date +%s)
	seconds="$(expr $end_time - $start_time)"
	time=""

	if [[ "$seconds" -gt 59 ]]
	then
		minutes=$(expr $seconds / 60)
		time="$minutes minutes"
	else
		time="$seconds seconds"
	fi

    echo -e "${BGreen}Your build completed successfully in $time! You should run axiom-update && axiom-build weekly to get the latest and greatest updates! ${Color_Off}"
    echo -e "${Green}To initialize an instance, run axiom-init${Color_Off}"
    "$NOTIFY_CMD" "Axiom Info" "Build completed successfully!"
else
   echo -e "${BRed}Your build failed :( Please take a look at the errors!${Color_Off}" 
   if [[ "$provider" ==  "linode" ]]; then
        echo -e "${Yellow}This can happen sometimes, if you have a [404] error while using Linode, this is likely because you need to request support for a larger image size${Color_Off}"
        echo -e "${Yellow}If you are using the default provisioner you need to request an increase to 25GB! ${Color_Off}"
        echo -e "${Yellow}You could try with another provisioner (reconftw is 14 GB in size) ${Color_Off}"
        echo -e "${Yellow}Use 'axiom-images ls' and delete any image before trying to build again ${Color_Off}"
   fi   
   echo -e "${Yellow}Verify the account is properly configured and/or try a different region.${Color_Off}"
   echo -e "${Yellow}For support, take a screenshot of the last 20 lines and open a issue at https://github.com/pry0cc/axiom/issues${Color_Off}"
   echo -e "${Green}Sometimes just running axiom-build again can work, so please try at least once: 'axiom-build', thanks!${Color_Off}" 
   "$NOTIFY_CMD" "Axiom Info" "Build failed :("
fi

if [[ $provisioner == "azure" ]]; then
    mv "$AXIOM_PATH/axiom_bck.json" "$AXIOM_PATH/axiom.json"
fi

############################################################################################################
# add data to account.json i.e account_path
#
jq '.op="'$op_ssh_password'"' <"$account_path">"$AXIOM_PATH"/tmp.json ; mv "$AXIOM_PATH"/tmp.json "$account_path"
jq '.imageid="'$snapshot_name'"' <"$account_path">"$AXIOM_PATH"/tmp.json ; mv "$AXIOM_PATH"/tmp.json "$account_path"
jq '.provisioner="'$provisioner'"' <"$account_path">"$AXIOM_PATH"/tmp.json ; mv "$AXIOM_PATH"/tmp.json "$account_path"
