#!/usr/bin/bash

# shellcheck disable=SC2016,SC1091

CLN_SERVER="https://cln.cloudlinux.com/cln/api/els/token/register"
CLN_UNREGISTER_SERVER="https://cln.cloudlinux.com/cln/api/els/token/unregister"
LICENSE=""
HOSTNAME="$(hostname)"
LOGFILE="/var/log/tuxctl.log"
FIPS_REGEX=" 9\.(2|6|10) "
HTTP_REGEX="HTTP/[0-3\.]+ 200 "

show_usage() {
    echo 'Usage: tuxctl [OPTION]...'
    echo ''
    echo '  -l, --license-key   User license key'
    echo '  -f, --force         Force re-register if TuxCare exists'
    echo '  -d, --delete        Delete license from server'
    echo '  -v, --validate      Check if server is registered'
    echo '  --fips, --FIPS      Enable FIPS repo and set as the only source of updates to FIPS packages'
    echo '  -u, --unlock-fips   Allow ESU security updates to replace FIPS packages'
    echo '  -s, --saas          Register a SaaS instance'
    echo '  -h, --help          Show this message and exit'
}

esu_installed() {
    if [[ -f /etc/dnf/vars/tuxcare_token ]]; then
        return 0
    else
        return 1
    fi
}

# exit if no arguments
if [ $# -lt 1 ]; then
    show_usage
    exit 0
fi

for opt in "$@"; do
    case ${opt} in
        -l|--license-key)
            LICENSE=$2 ; shift ;;
        -f|--force)
            FORCE=true ; shift ;;
        -d|--delete)
            DELETE=true ; shift ;;
        -v|--validate)
            VALIDATE=true ; shift ;;
        --fips|--FIPS)
            FIPS=true ; shift ;;
        -u|--unlock-fips)
            UNLOCK=true ; shift ;;
        -s|--saas)
            SAAS=true ; shift ;;
        -h|--help)
            show_usage ; exit 0 ;;
    esac
done

# check if it is not running under root
if [ "$EUID" -ne 0 ]; then
    echo "Please run as root"
    exit 1
fi

if [[ -n $VALIDATE ]]; then
    if esu_installed; then
        echo "Server is registered with token $(cat /etc/dnf/vars/tuxcare_token)"
        exit 0
    else
        echo "Server is not registered"
        exit 1
    fi
fi

if [[ -n $FORCE ]]; then
    rm -f /etc/dnf/vars/tuxcare_token
fi

# unregister server
if [[ -n $DELETE ]]; then
    if ! esu_installed; then
        echo "Server is not registered"
        exit 1
    fi

    # delete is not currently supported with eportal
    if [[ -f /etc/sysconfig/tuxcare/eportal.env ]]; then
        echo "De-registration is not supported with eportal"
        exit 1
    fi

    CLN_UNREGISTER=$(curl -s -i -X POST "$CLN_UNREGISTER_SERVER?token=$(cat /etc/dnf/vars/tuxcare_token)")

    if [[ ! "$CLN_UNREGISTER" =~ $HTTP_REGEX ]]; then
        echo "Got incorrect status from CLN: $CLN_UNREGISTER"
        exit 1
    else
        echo "De-registration successful"
        rm -f /etc/dnf/vars/tuxcare_token
        exit 0
    fi
fi

# check architecture
ARCH=$(uname -i)
case "${ARCH}" in
    x86_64|aarch64)
        ;;
    *)
        echo "ERROR: ${ARCH} architecture is not supported by tuxctl"
        exit 1
        ;;
esac

# check almalinux-release file
if [[ ! -f /etc/almalinux-release ]]; then
    echo "ERROR: This server is not AlmaLinux based"
    exit 1
fi

almalinux_release="$(cat /etc/almalinux-release)"

if [[ ! -f /etc/dnf/vars/tuxcare_releasever ]]; then
    echo "ERROR: This server doesn't have TuxCare. Please install tuxcare-release package"
    exit 1
fi

# check if TuxCare is installed
if [[ -f /etc/dnf/vars/tuxcare_token && -z $FIPS  && -z $UNLOCK ]]; then
    echo "This server already has an TuxCare token installed"
    echo "To force re-registration, please run the script with --force"
    exit 1
fi

if [[ -n $FIPS && -n $UNLOCK ]]; then
    echo "--fips and --unlock-fips cannot be used at the same time."
    exit 1
fi

if [[ -n $FIPS ]]; then
    if [[ ! "${almalinux_release}" =~ $FIPS_REGEX ]]; then
        echo "This server is not running a FIPS release."
        exit 1
    fi

    # enable FIPS repo
    dnf config-manager --set-enabled tuxcare-fips

    # add excludes
    grep -q "exclude=\$tuxcare_fips_excludes" /etc/yum.repos.d/*.repo ||
        sed -i -e '/gpgkey=/a exclude=$tuxcare_fips_excludes' \
            /etc/yum.repos.d/almalinux*.repo /etc/yum.repos.d/tuxcare-esu.repo

    echo "FIPS repository installed successfully"
    echo "Please see docs.tuxcare.com for instructions regarding enabling FIPS mode"

    # exit if we're not registering
    if [[ -f /etc/dnf/vars/tuxcare_token ]]; then
        exit 1
    fi
fi

if [[ -n $UNLOCK ]]; then
    if [[ ! "${almalinux_release}" =~ $FIPS_REGEX ]]; then
        echo "This server is not running a FIPS release."
        exit 1
    fi

    # disable fips repo
    dnf config-manager --set-enabled tuxcare-esu
    dnf config-manager --set-disabled tuxcare-fips

    # remove excludes
    sed -i '/^exclude=$tuxcare_fips_excludes/d' /etc/yum.repos.d/*.repo

    echo "FIPS packages are unlocked and could be replaced by ESU security updates"
    echo "If you do not want this behaviour, please run tuxctl --fips"
    exit 1
fi

####################################################################
# The code below is used to register the server in CLN or eportal, obtain a token and configure ESU repositories

if [[ -n $SAAS ]]; then
    # register a saas instance, first get an imds token
    AWS_TOKEN=$(curl -m2 -sX PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
    AWS_EXITCODE=$?

    # if exit code is non-zero then its probably not in AWS
    if [[ ! "$AWS_EXITCODE" == 0 ]]; then
        echo "ERROR: Cannot connect to AWS metadata service"
        exit 1
    fi

    # fetch accountid using token
    AWS_ACCOUNTID="$(curl -sH "X-aws-ec2-metadata-token: $AWS_TOKEN" http://169.254.169.254/latest/dynamic/instance-identity/document | awk -F\" '/accountId/{print $4;}')"

    # check accountid syntax, could be wrong cloud provider
    if [[ ! "$AWS_ACCOUNTID" =~ ^[0-9]{12}$ ]]; then
        echo "ERROR: Invalid AWS account ID"
        exit 1
    fi

    # custom aws license key
    LICENSE="ESU-AWS-$AWS_ACCOUNTID"
fi

if [[ -f /etc/sysconfig/tuxcare/eportal.env ]]; then
    # defines $EPORTAL_TUXCARE_REPO and $CLN_TUXCARE_TOKEN
    . /etc/sysconfig/tuxcare/eportal.env
else
    # get token
    CLN_REGISTER=$(curl -s -i -X POST -H "Content-Type: application/json" -H "accept: */*" -d "{\"key\": \"$LICENSE\", \"host_name\": \"$HOSTNAME\"}" "$CLN_SERVER")
    echo "CLN server answer:" >> $LOGFILE
    echo "$CLN_REGISTER" >> $LOGFILE
    if [[ ! "$CLN_REGISTER" =~ $HTTP_REGEX ]]; then
        echo "ERROR: Got incorrect status from CLN: $CLN_REGISTER"
        exit 1
    fi

    CLN_TUXCARE_TOKEN=$(echo "$CLN_REGISTER" | grep -oP '"token":"\K[\w\d-]*')
    if [[ -z $CLN_TUXCARE_TOKEN ]]; then
        echo "ERROR: Something went wrong. Token is not defined"
        echo "Check $LOGFILE for details"
        exit 1
    fi

    CLN_PRODUCT_ID=$(echo "$CLN_REGISTER" | grep -oP '"product_id":\K[\w\d-]*')
    if [[ -z $CLN_PRODUCT_ID ]]; then
        echo "ERROR: Something went wrong. Product ID is not defined"
        echo "Check $LOGFILE for details"
        exit 1
    fi
fi

# Setting "updates" repo
echo "${CLN_TUXCARE_TOKEN}" > /etc/dnf/vars/tuxcare_token

# check if there is an eportal proxy and switch tuxcare repos to it
if [[ -n "$EPORTAL_TUXCARE_REPO" ]]; then
    sed -ri \
        -e "s|^baseurl=.+/tuxcare/|baseurl=$EPORTAL_TUXCARE_REPO|" \
        /etc/yum.repos.d/tuxcare-*.repo
fi

# enable ESU repo if we are running a FIPS release
if [[ "${almalinux_release}" =~ $FIPS_REGEX ]]; then
    dnf config-manager --set-enabled tuxcare-esu
fi

rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-TuxCare
echo "TuxCare installed successfully"
